<pre class=metadata>
Group: WHATWG
H1: Fetch
Shortname: fetch
Text Macro: TWITTER fetchstandard
Abstract: The Fetch standard defines requests, responses, and the process that binds them: fetching.
Translation: ja https://triple-underscore.github.io/Fetch-ja.html
Markup Shorthands: css off
Translate IDs: typedefdef-bodyinit bodyinit,dictdef-requestinit requestinit,typedefdef-requestinfo requestinfo,enumdef-requestdestination requestdestination,enumdef-requestmode requestmode,enumdef-requestcredentials requestcredentials,enumdef-requestcache requestcache,enumdef-requestredirect requestredirect,dictdef-responseinit responseinit,enumdef-responsetype responsetype
</pre>

<pre class=anchors>
url:https://tools.ietf.org/html/rfc7230#section-3.1.1;text:method;type:dfn;spec:http
url:https://tools.ietf.org/html/rfc7230#section-3.2;text:field-name;type:dfn;spec:http
url:https://tools.ietf.org/html/rfc7230#section-3.2;text:field-content;type:dfn;spec:http
url:https://tools.ietf.org/html/rfc7230#section-3.2;text:field-value;type:dfn;spec:http
url:https://tools.ietf.org/html/rfc7230#section-3.1.2;text:reason-phrase;type:dfn;spec:http
url:https://tools.ietf.org/html/rfc7234#section-1.2.1;text:delta-seconds;type:dfn;spec:http-caching
url:https://tools.ietf.org/html/draft-ietf-httpbis-header-structure#section-2;text:structured header value;type:dfn;spec:header-structure
url:https://tools.ietf.org/html/draft-ietf-httpbis-header-structure#section-4.1;text:serializing structured headers;type:dfn;spec:header-structure
url:https://tools.ietf.org/html/draft-ietf-httpbis-header-structure#section-4.2;text:parsing structured headers;type:dfn;spec:header-structure
</pre>

<pre class=biblio>
{
    "HTTP": {
        "aliasOf": "RFC7230"
    },
    "HTTP-SEMANTICS": {
        "aliasOf": "RFC7231"
    },
    "HTTP-COND": {
        "aliasOf": "RFC7232"
    },
    "HTTP-CACHING": {
        "aliasOf": "RFC7234"
    },
    "HTTP-RANGE": {
        "aliasOf": "RFC7233"
    },
    "HTTP-AUTH": {
        "aliasOf": "RFC7235"
    },
    "REFERRER": {
        "aliasOf": "referrer-policy"
    },
    "STALE-WHILE-REVALIDATE": {
        "aliasOf": "RFC5861"
    },
    "SW": {
        "aliasOf": "service-workers"
    },
    "UPGRADE": {
        "aliasOf": "upgrade-insecure-requests"
    },
    "HSTS": {
        "aliasOf": "RFC6797"
    },
    "WSP": {
        "aliasOf": "RFC6455"
    },
    "HTTPVERBSEC1": {
        "publisher": "US-CERT",
        "href": "https://www.kb.cert.org/vuls/id/867593",
        "title": "Multiple vendors' web servers enable HTTP TRACE method by default."
    },
    "HTTPVERBSEC2": {
        "publisher": "US-CERT",
        "href": "https://www.kb.cert.org/vuls/id/288308",
        "title": "Microsoft Internet Information Server (IIS) vulnerable to cross-site scripting via HTTP TRACK method."
    },
    "HTTPVERBSEC3": {
        "publisher": "US-CERT",
        "href": "https://www.kb.cert.org/vuls/id/150227",
        "title": "HTTP proxy default configurations allow arbitrary TCP connections."
    },
    "EXPECT-CT": {
        "authors": [
            "Emily Stark"
        ],
        "href": "https://tools.ietf.org/html/draft-ietf-httpbis-expect-ct-02",
        "publisher": "IETF",
        "title": "Expect-CT Extension for HTTP"
    },
    "OCSP": {
        "aliasOf": "RFC2560"
    },
    "HEADER-STRUCTURE": {
        "authors": ["Mark Nottingham","Paul-Henning Kamp"],
        "href": "https://tools.ietf.org/html/draft-ietf-httpbis-header-structure",
        "publisher": "IETF",
        "title": "Structured Headers for HTTP"
    }
}
</pre>

<pre class=link-defaults>
spec:infra; type:dfn; text:string
</pre>



<h2 id=goals class="no-num short">Goals</h2>

<p>To unify fetching across the web platform this specification supplants a number of algorithms and
specifications:

<ul class="brief no-backref">
 <li>HTML Standard's fetch and potentially CORS-enabled fetch algorithms
 [[HTML]]
 <li>CORS [[CORS]]
 <li>HTTP `<a http-header><code>Origin</code></a>` header semantics
 [[ORIGIN]]
</ul>

<p>Unifying fetching provides consistent handling of:

<ul class=brief>
 <li>URL schemes
 <li>Redirects
 <li>Cross-origin semantics
 <li>CSP [[!CSP]]
 <li>Service workers [[!SW]]
 <li>Mixed Content [[!MIX]]
 <li>`<code>Referer</code>` [[!REFERRER]]
</ul>



<h2 id=preface class=short>Preface</h2>

<p>At a high level, fetching a resource is a fairly simple operation. A request goes in, a
response comes out. <!--You can't explain that! -->The details of that operation are
however quite involved and used to not be written down carefully and differ from one API
to the next.

<p>Numerous APIs provide the ability to fetch a resource, e.g. HTML's <code>img</code> and
<code>script</code> element, CSS' <code>cursor</code> and <code>list-style-image</code>,
the <code>navigator.sendBeacon()</code> and <code>self.importScripts()</code> JavaScript
APIs. The Fetch Standard provides a unified architecture for these features so they are
all consistent when it comes to various aspects of fetching, such as redirects and the
CORS protocol.

<p>The Fetch Standard also defines the <a><code>fetch()</code></a>
JavaScript API, which exposes most of the networking functionality at a fairly low level
of abstraction.



<h2 id=infrastructure>Infrastructure</h2>

<p>This specification depends on the Infra Standard. [[!INFRA]]

<p>This specification uses terminology from the ABNF, Encoding, HTML, HTTP, IDL, MIME Sniffing,
Streams, and URL Standards.
[[!ABNF]]
[[!ENCODING]]
[[!HTML]]
[[!HTTP]]
[[!WEBIDL]]
[[!MIMESNIFF]]
[[!STREAMS]]
[[!URL]]

<p><dfn>ABNF</dfn> means ABNF as augmented by HTTP (in particular the addition <code>#</code>) and
RFC 7405. [[!RFC7405]]

<hr>

<p><dfn id=credentials export>Credentials</dfn> are HTTP cookies, TLS client certificates, and <a
lt="authentication entry">authentication entries</a> (for HTTP authentication). [[!COOKIES]]
[[!TLS]] [[!HTTP-AUTH]]

<hr>

<p><a>Tasks</a> that are
<a lt="queue a task">queued</a> by this standard are annotated as one
of:

<ul class=brief>
 <li><dfn export>process request body</dfn>
 <li id=process-request-end-of-file><dfn export>process request end-of-body</dfn>
 <li><dfn export>process response</dfn>
 <li id=process-response-end-of-file><dfn export>process response end-of-body</dfn>
 <li><dfn export>process response done</dfn>
</ul>

<p>To <dfn>queue a fetch task</dfn> on <a for=/>request</a>
<var>request</var> to <var>run an operation</var>, run these steps:

<ol>
 <li><p>If <var>request</var>'s <a for=request>client</a> is
 null, terminate these steps.

 <li><p><a>Queue a task</a> to
 <var>run an operation</var> on <var>request</var>'s
 <a for=request>client</a>'s
 <a>responsible event loop</a> using the
 <a>networking task source</a>.
</ol>

<p>To <dfn>queue a fetch-request-done task</dfn>, given a <var>request</var>,
<a>queue a fetch task</a> on <var>request</var> to <a>process request end-of-body</a>
for <var>request</var>.

<p>To <dfn>serialize an integer</dfn>, represent it as a string of the shortest possible decimal
number.

<p class=XXX>This will be replaced by a more descriptive algorithm in Infra. See
<a href="https://github.com/whatwg/infra/issues/201">infra/201</a>.


<h3 id=url>URL</h3>

<p>A <dfn export>local scheme</dfn> is a <a for=url>scheme</a> that is "<code>about</code>",
"<code>blob</code>", or "<code>data</code>".

<p>A <a for=/>URL</a> <dfn export>is local</dfn> if its <a for=url>scheme</a> is a
<a>local scheme</a>.

<p class=note>This definition is also used by <cite>Referrer Policy</cite>. [[REFERRER]]

<p>An <dfn export id=http-scheme>HTTP(S) scheme</dfn> is a <a for=url>scheme</a> that is
"<code>http</code>" or "<code>https</code>".

<p>A <dfn export>network scheme</dfn> is a <a for=url>scheme</a> that is "<code>ftp</code>" or an
<a>HTTP(S) scheme</a>.

<p>A <dfn export>fetch scheme</dfn> is a <a for=url>scheme</a> that is "<code>about</code>",
"<code>blob</code>", "<code>data</code>", "<code>file</code>", or a <a>network scheme</a>.

<p class="note no-backref"><a>HTTP(S) scheme</a>, <a>network scheme</a>, and <a>fetch scheme</a> are
also used by <cite>HTML</cite>. [[HTML]]

<hr>

<p id=fetch-url>A <dfn>response URL</dfn> is a <a for=/>URL</a> for which implementations need not
store the <a for=url>fragment</a> as it is never exposed. When
<a lt="url serializer">serialized</a>, the <i>exclude fragment flag</i> is set, meaning
implementations can store the <a for=url>fragment</a> nonetheless.


<h3 id=http>HTTP</h3>

<p>While <a lt=fetch for=/>fetching</a> encompasses more than just HTTP, it
borrows a number of concepts from HTTP and applies these to resources obtained via other
means (e.g., <code>data</code> URLs).

<p>An <dfn export>HTTP tab or space</dfn> is U+0009 TAB or U+0020 SPACE.

<p><dfn export>HTTP whitespace</dfn> is U+000A LF, U+000D CR, or an <a>HTTP tab or space</a>.

<p class="note no-backref"><a>HTTP whitespace</a> is only useful for specific constructs that are
reused outside the context of HTTP headers (e.g., <a for=/>MIME types</a>). For HTTP header values,
using <a>HTTP tab or space</a> is preferred, and outside that context <a>ASCII whitespace</a> is
preferred. Unlike <a>ASCII whitespace</a> this excludes U+000C FF.

<p>An <dfn export>HTTP newline byte</dfn> is 0x0A (LF) or 0x0D (CR).

<p>An <dfn export>HTTP tab or space byte</dfn> is 0x09 (HT) or 0x20 (SP).

<p>An <dfn export>HTTP whitespace byte</dfn> is an <a>HTTP newline byte</a> or
<a>HTTP tab or space byte</a>.

<p>An <dfn export id=concept-https-state-value>HTTPS state value</dfn> is "<code>none</code>",
"<code>deprecated</code>", or "<code>modern</code>".

<p class="note no-backref">A <a for=/>response</a> delivered over HTTPS will
typically have its <a for=response>HTTPS state</a> set to
"<code>modern</code>". A user agent can use "<code>deprecated</code>" in a transition
period. E.g., while removing support for a hash function, weak cipher suites, certificates for an
"Internal Name", or certificates with an overly long validity period. How exactly a user agent can
use "<code>deprecated</code>" is not defined by this specification. An
<a>environment settings object</a> typically derives its
<a for="environment settings object">HTTPS state</a> from a <a for=/>response</a>.

<p>To
<dfn export lt="collect an HTTP quoted string|collecting an HTTP quoted string">collect an HTTP quoted string</dfn>
from a <a for=/>string</a> <var>input</var>, given a <a>position variable</a> <var>position</var>
and optionally an <var>extract-value flag</var>, run these steps:

<ol>
 <li><p>Let <var>positionStart</var> be <var>position</var>.

 <li><p>Let <var>value</var> be the empty string.

 <li><p>Assert: the <a>code point</a> at <var>position</var> within <var>input</var> is U+0022 (").

 <li><p>Advance <var>position</var> by 1.

 <li>
  <p>While true:

  <ol>
   <li><p>Append the result of <a>collecting a sequence of code points</a> that are not U+0022 (")
   or U+005C (\) from <var>input</var>, given <var>position</var>, to <var>value</var>.

   <li><p>If <var>position</var> is past the end of <var>input</var>, then
   <a for=iteration>break</a>.

   <li><p>Let <var>quoteOrBackslash</var> be the <a>code point</a> at <var>position</var> within
   <var>input</var>.

   <li><p>Advance <var>position</var> by 1.

   <li>
    <p>If <var>quoteOrBackslash</var> is U+005C (\), then:

    <ol>
     <li><p>If <var>position</var> is past the end of <var>input</var>, then append U+005C (\) to
     <var>value</var> and <a for=iteration>break</a>.

     <li><p>Append the <a>code point</a> at <var>position</var> within <var>input</var> to
     <var>value</var>.

     <li><p>Advance <var>position</var> by 1.
    </ol>

   <li>
    <p>Otherwise:

    <ol>
     <li><p>Assert: <var>quoteOrBackslash</var> is U+0022 (").

     <li><p><a for=iteration>Break</a>.
    </ol>
  </ol>

 <li><p>If the <var>extract-value flag</var> is set, then return <var>value</var>.

 <li><p>Return the <a for=/>code points</a> from <var>positionStart</var> to <var>position</var>,
 inclusive, within <var>input</var>.
</ol>

<p class="note no-backref">The <var>extract-value flag</var> argument makes this algorithm suitable
for <a for="header list">getting, decoding, and splitting</a> and <a>parse a MIME type</a>, as well
as other header value parsers that might need this.


<h4 id=methods>Methods</h4>

<p>A <dfn export id=concept-method>method</dfn> is a byte sequence that matches the
<a spec=http>method</a> token production.

<p id=simple-method>A <dfn export>CORS-safelisted method</dfn> is a
<a for=/>method</a> that is `<code>GET</code>`,
`<code>HEAD</code>`, or `<code>POST</code>`.

<p>A <dfn export>forbidden method</dfn> is a <a for=/>method</a> that is a
<a>byte-case-insensitive</a> match for `<code>CONNECT</code>`,
`<code>TRACE</code>`, or `<code>TRACK</code>`.
[[HTTPVERBSEC1]], [[HTTPVERBSEC2]], [[HTTPVERBSEC3]]

<p>To <dfn export for=method id=concept-method-normalize>normalize</dfn> a
<a for=/>method</a>, if it is a <a>byte-case-insensitive</a>
match for `<code>DELETE</code>`, `<code>GET</code>`,
`<code>HEAD</code>`, `<code>OPTIONS</code>`, `<code>POST</code>`, or
`<code>PUT</code>`, <a>byte-uppercase</a> it.

<p class="note no-backref"><a lt=normalize for=method>Normalization</a> is
done for backwards compatibility and consistency across APIs as
<a for=/>methods</a> are actually "case-sensitive".

<p id=example-normalization class=example>Using `<code>patch</code>` is highly likely to result in a
`<code>405 Method Not Allowed</code>`. `<code>PATCH</code>` is much more likely to
succeed.

<p class="note no-backref">There are no restrictions on <a for=/>methods</a>.
`<code>CHICKEN</code>` is perfectly acceptable (and not a misspelling of
`<code>CHECKIN</code>`). Other than those that are
<a lt=normalize for=method>normalized</a> there are no casing restrictions either.
`<code>Egg</code>` or `<code>eGg</code>` would be fine, though uppercase is encouraged
for consistency.


<h4 id=terminology-headers>Headers</h4>

<p>A <dfn export id=concept-header-list>header list</dfn> is a <a for=/>list</a> of zero or more
<a for=/>headers</a>. It is initially the empty list.

<p class="note no-backref">A <a for=/>header list</a> is essentially a
specialized multimap. An ordered list of key-value pairs with potentially duplicate keys.

<p>To
<dfn export for="header list" id=concept-header-list-get-structured-header>get a structured header</dfn>
given a <var>name</var> and a <var>type</var> from a <a for=/>header list</a> <var>list</var>, run
these steps:

<ol>
 <li><p>Assert: <var>type</var> is one of "<code>dictionary</code>", "<code>list</code>", or
 "<code>item</code>".

 <li><p>Let <var>value</var> be the result of <a for="header list">getting</a> <var>name</var> from
 <var>list</var>.

 <li><p>If <var>value</var> is null, then return null.

 <li><p>Let <var>result</var> be the result of executing the <a>parsing structured headers</a>
 algorithm with <var ignore>input_string</var> set to <var>value</var>, and
 <var ignore>header_type</var> set to <var>type</var>.

 <li><p>If parsing failed, then return failure.

 <li><p>Return <var>result</var>.
</ol>

<p>To
<dfn export for="header list" id=concept-header-list-set-structured-header>set a structured header</dfn>
<a for=header>name</a>/<a>structured header value</a> <var>name</var>/<var>structuredValue</var>
pair in a <a for=/>header list</a> <var>list</var>, run these steps:

<ol>
 <li><p>Let <var>serializedValue</var> be the result of executing the
 <a>serializing structured headers</a> algorithm on <var>structuredValue</var>.

 <li><p><a for="header list">Set</a> <var>name</var>/<var>serializedValue</var> in <var>list</var>.
</ol>

<p class=note><a>Structured header values</a> are defined as objects which HTTP can (eventually)
serialize in interesting and efficient ways. For the moment, Fetch only supports <a for=/>header</a>
<a for=header>values</a> as <a for=/>byte sequences</a>, which means that these objects can be set
in <a for=/>header lists</a> only via serialization, and they can be obtained from
<a for=/>header lists</a> only by parsing. In the future the fact that they are objects might be
preserved end-to-end. [[!HEADER-STRUCTURE]]

<hr>

<p>A <a for=/>header list</a> <var>list</var>
<dfn export for="header list" lt="contains|does not contain">contains</dfn> a <a for=header>name</a>
<var>name</var> if <var>list</var> <a for=list>contains</a> a <a for=/>header</a> whose
<a for=header>name</a> is a <a>byte-case-insensitive</a> match for <var>name</var>.

<p>To <dfn export for="header list" id=concept-header-list-get>get</dfn> a <a for=header>name</a>
<var>name</var> from a <a for=/>header list</a> <var>list</var>, run these steps:

<ol>
 <li><p>If <var>list</var> <a for="header list">does not contain</a> <var>name</var>, then return
 null.

 <li><p>Return the <a lt=value for=header>values</a> of all <a for=/>headers</a> in <var>list</var>
 whose <a for=header>name</a> is a <a>byte-case-insensitive</a> match for <var>name</var>, separated
 from each other by 0x2C 0x20, in order.
</ol>

<p>To
<dfn export for="header list" lt="get, decode, and split|getting, decoding, and splitting" id=concept-header-list-get-decode-split>get, decode, and split</dfn>
a <a for=header>name</a> <var>name</var> from <a for=/>header list</a> <var>list</var>, run these
steps:

<ol>
 <li><p>Let <var>initialValue</var> be the result of <a for="header list">getting</a>
 <var>name</var> from <var>list</var>.

 <li><p>If <var>initialValue</var> is null, then return null.

 <li><p>Let <var>input</var> be the result of <a>isomorphic decoding</a> <var>initialValue</var>.

 <li><p>Let <var>position</var> be a <a for=string>position variable</a> for <var>input</var>,
 initially pointing at the start of <var>input</var>.

 <li><p>Let <var>values</var> be a <a for=/>list</a> of <a for=/>strings</a>, initially empty.

 <li><p>Let <var>value</var> be the empty string.

 <li>
  <p>While <var>position</var> is not past the end of <var>input</var>:

  <ol>
   <li>
    <p>Append the result of <a>collecting a sequence of code points</a> that are not U+0022 (") or
    U+002C (,) from <var>input</var>, given <var>position</var>, to <var>value</var>.

    <p class=note>The result might be the empty string.

   <li>
    <p>If <var>position</var> is not past the end of <var>input</var>, then:

    <ol>
     <li>
      <p>If the <a for=/>code point</a> at <var>position</var> within <var>input</var> is
      U+0022 ("), then:

      <ol>
       <li><p>Append the result of <a>collecting an HTTP quoted string</a> from <var>input</var>,
       given <var>position</var>, to <var>value</var>.

       <li>If <var>position</var> is not past the end of <var>input</var>, then
       <a for=iteration>continue</a>.
      </ol>

     <li>
      <p>Otherwise:

      <ol>
       <li><p>Assert: the <a for=/>code point</a> at <var>position</var> within <var>input</var> is
       U+002C (,).

       <li><p>Advance <var>position</var> by 1.
      </ol>
    </ol>

   <li><p>Remove all <a>HTTP tab or space</a> from the start and end of <var>value</var>.

   <li><p><a for=list>Append</a> <var>value</var> to <var>values</var>.

   <li><p>Set <var>value</var> to the empty string.
  </ol>

 <li><p>Return <var>values</var>.
</ol>

<div class=example id=example-header-list-get-decode-split>
 <p>This is how <a>get, decode, and split</a> functions in practice with `<code>A</code>` as the
 <var>name</var> argument:

 <table>
  <tr>
   <th>Headers (as on the network)
   <th>Output
  <tr>
   <td>
    <pre><code class=lang-http>
A: nosniff,
</code></pre>
   <td rowspan=2>« "<code>nosniff</code>", "" »
  <tr>
   <td>
    <pre><code class=lang-http>
A: nosniff
B: sniff
A:
</code></pre>
  <tr>
   <td>
    <pre><code class=lang-http>A: text/html;", x/x</code></pre>
   <td rowspan=2>« "<code>text/html;", x/x</code>" »
  <tr>
   <td>
    <pre><code class=lang-http>
A: text/html;"
A: x/x
</code></pre>
  <tr>
   <td>
    <pre><code class=lang-http>
A: x/x;test="hi",y/y
</code></pre>
   <td rowspan=2>« "<code>x/x;test="hi"</code>", "<code>y/y</code>" »
  <tr>
   <td>
    <pre><code class=lang-http>
A: x/x;test="hi"
C: **bingo**
A: y/y
</code></pre>
  <tr>
   <td>
    <pre><code class=lang-http>
A: x / x,,,1
</code></pre>
   <td rowspan=2>« "<code>x / x</code>", "", "", "<code>1</code>" »
  <tr>
   <td>
    <pre><code class=lang-http>
A: x / x
A: ,
A: 1
</code></pre>
  <tr>
   <td>
    <pre><code class=lang-http>
A: "1,2", 3
</code></pre>
   <td rowspan=2>« "<code>"1,2"</code>", "<code>3</code>" »
  <tr>
   <td>
    <pre><code class=lang-http>
A: "1,2"
D: 4
A: 3
</code></pre>
 </table>
</div>

<p>To <dfn export for="header list" id=concept-header-list-append>append</dfn> a
<a for=header>name</a>/<a for=header>value</a> <var>name</var>/<var>value</var> pair to a
<a for=/>header list</a> <var>list</var>, run these steps:

<ol>
 <li>
  <p>If <var>list</var> <a for="header list">contains</a> <var>name</var>, then set <var>name</var>
  to the first such <a for=/>header</a>'s <a for=header>name</a>.

  <p class="note no-backref">This reuses the casing of the <a for=header>name</a> of the
  <a for=/>header</a> already in <var>list</var>, if any. If there are multiple matched
  <a for=/>headers</a> their <a for=header>names</a> will all be identical.

 <li><p><a for=list>Append</a> a new <a for=/>header</a> whose <a for=header>name</a> is
 <var>name</var> and <a for=header>value</a> is <var>value</var> to <var>list</var>.
</ol>

<p>To <dfn export for="header list" id=concept-header-list-delete>delete</dfn> a
<a for=header>name</a> <var>name</var> from a <a for=/>header list</a> <var>list</var>,
<a for=list>remove</a> all <a for=/>headers</a> whose <a for=header>name</a> is a
<a>byte-case-insensitive</a> match for <var>name</var> from <var>list</var>.

<p>To <dfn export for="header list" id=concept-header-list-set>set</dfn> a
<a for=header>name</a>/<a for=header>value</a> <var>name</var>/<var>value</var> pair in a
<a for=/>header list</a> <var>list</var>, run these steps:

<ol>
 <li><p>If <var>list</var> <a for="header list">contains</a> <var>name</var>, then set the
 <a for=header>value</a> of the first such <a for=/>header</a> to <var>value</var> and
 <a for=list>remove</a> the others.

 <li><p>Otherwise, <a for=list>append</a> a new <a for=/>header</a> whose <a for=header>name</a> is
 <var>name</var> and <a for=header>value</a> is <var>value</var> to <var>list</var>.
</ol>

<p>To <dfn export for="header list" id=concept-header-list-combine>combine</dfn> a
<a for=header>name</a>/<a for=header>value</a> <var>name</var>/<var>value</var> pair in a
<a for=/>header list</a> <var>list</var>, run these steps:

<ol>
 <li><p>If <var>list</var> <a for="header list">contains</a> <var>name</var>, then set the
 <a for=header>value</a> of the first such <a for=/>header</a> to its <a for=header>value</a>,
 followed by 0x2C 0x20, followed by <var>value</var>.

 <li><p>Otherwise, <a for=list>append</a> a new <a for=/>header</a> whose <a for=header>name</a> is
 <var>name</var> and <a for=header>value</a> is <var>value</var> to <var>list</var>.
</ol>

<p class="note no-backref"><a for="header list">Combine</a> is used by {{XMLHttpRequest}} and the
<a lt="establish a WebSocket connection">WebSocket protocol handshake</a>.

<p>To <dfn>convert header names to a sorted-lowercase set</dfn>, given a <a for=/>list</a> of
<a lt=name for=header>names</a> <var>headerNames</var>, run these steps:

<ol>
 <li><p>Let <var>headerNamesSet</var> be a new <a for/>ordered set</a>.

 <li><p><a for=list>For each</a> <var>name</var> of <var>headerNames</var>, <a for=set>append</a>
 the result of <a lt=byte-lowercased>byte-lowercasing</a> <var>name</var> to
 <var>headerNamesSet</var>.

 <li><p>Return the result of <a for=set>sorting</a> <var>headerNamesSet</var> in ascending order
 with <a>byte less than</a>.
</ol>

<p>To
<dfn export for="header list" id=concept-header-list-sort-and-combine>sort and combine</dfn>
a <a for=/>header list</a> <var>list</var>, run these steps:

<ol>
 <li><p>Let <var>headers</var> be an empty <a for=/>list</a> of
 <a for=header>name</a>-<a for=header>value</a> pairs with the key being the <a for=header>name</a>
 and value the <a for=header>value</a>.

 <li><p>Let <var>names</var> be the result of
 <a>convert header names to a sorted-lowercase set</a> with all the <a lt=name for=header>names</a>
 of the <a for=/>headers</a> in <var>list</var>.

 <li>
  <p><a for=list>For each</a> <var>name</var> in <var>names</var>:

  <ol>
   <li><p>Let <var>value</var> be the result of <a for="header list">getting</a> <var>name</var>
   from <var>list</var>.

   <li><p>Assert: <var>value</var> is not null.

   <li><p><a for=list>Append</a> <var>name</var>-<var>value</var> to <var>headers</var>.
  </ol>

 <li><p>Return <var>headers</var>.
</ol>

<hr>

<p>A <dfn export id=concept-header>header</dfn> consists of a
<dfn export for=header id=concept-header-name>name</dfn> and
<dfn export for=header id=concept-header-value>value</dfn>.

<p>A <a for=header>name</a> is a <a>byte sequence</a> that matches the <a spec=http>field-name</a>
token production.

<p>A <a for=header>value</a> is a <a>byte sequence</a> that matches the following conditions:

<ul class=brief>
 <li><p>Has no leading or trailing <a>HTTP tab or space bytes</a>.
 <li><p>Contains no 0x00 (NUL) or <a>HTTP newline bytes</a>.
</ul>

<p class=note>The definition of <a for=header>value</a> is not defined in terms of an HTTP token
production as
<a href=https://github.com/httpwg/http11bis/issues/19 title="fix field-value ABNF">it is broken</a>.

<p>To <dfn export for=header/value id=concept-header-value-normalize>normalize</dfn> a
<var>potentialValue</var>, remove any leading and trailing <a>HTTP whitespace bytes</a> from
<var>potentialValue</var>.

<hr>

<p id=simple-header>To determine whether a <a for=/>header</a> <var>header</var> is a
<dfn export>CORS-safelisted request-header</dfn>, run these steps:

<ol>
 <li><p>Let <var>value</var> be <var>header</var>'s <a for=header>value</a>.

 <li>
  <p><a>Byte-lowercase</a> <var>header</var>'s <a for=header>name</a> and switch on the result:

  <dl class=switch>
   <dt>`<code>accept</code>`
   <dd>
    <p>If <var>value</var> contains a <a>CORS-unsafe request-header byte</a>, then return false.

   <dt>`<code>accept-language</code>`
   <dt>`<code>content-language</code>`
   <dd><p>If <var>value</var> contains a byte that is not in the range 0x30 (0) to 0x39 (9),
   inclusive, is not in the range 0x41 (A) to 0x5A (Z), inclusive, is not in the range 0x61 (a) to
   0x7A (z), inclusive, and is not 0x20 (SP), 0x2A (*), 0x2C (,), 0x2D (-), 0x2E (.), 0x3B (;), or
   0x3D (=), then return false.
   <!-- Maybe give Infra "byte-alphanumeric"? -->

   <dt>`<code>content-type</code>`
   <dd>
    <ol>
     <li><p>If <var>value</var> contains a <a>CORS-unsafe request-header byte</a>, then return
     false.

     <li><p>Let <var>mimeType</var> be the result of <a lt="parse a MIME type">parsing</a>
     <var>value</var>.

     <li><p>If <var>mimeType</var> is failure, then return false.

     <li><p>If <var>mimeType</var>'s <a for="MIME type">essence</a> is not
     "<code>application/x-www-form-urlencoded</code>", "<code>multipart/form-data</code>", or
     "<code>text/plain</code>", then return false.
    </ol>

    <p class=warning>This intentionally does not use <a>extract a MIME type</a> as that algorithm is
    rather forgiving and servers are not expected to implement it.

    <div class="example no-backref" id=example-cors-safelisted-request-header-content-type>
     <p>If <a>extract a MIME type</a> were used the following request would not result in a CORS
     preflight and a naïve parser on the server might treat the request body as JSON:

     <pre><code class=lang-javascript>
fetch("https://victim.example/naïve-endpoint", {
  method: "POST",
  headers: [
    ["Content-Type", "application/json"],
    ["Content-Type", "text/plain"]
  ],
  credentials: "include",
  body: JSON.stringify(exerciseForTheReader)
});
</code></pre>
    </div>

   <dt>Otherwise
   <dd><p>Return false.
  </dl>

 <li><p>If <var>value</var>'s <a for="byte sequence">length</a> is greater than 128, then return
 false.

 <li><p>Return true.
</ol>

<p class="note">There are limited exceptions to the `<code>Content-Type</code>` header safelist, as
documented in <a href=#cors-protocol-exceptions>CORS protocol exceptions</a>.

<p>A <dfn>CORS-unsafe request-header byte</dfn> is a byte <var>byte</var> for which one of the
following is true:

<ul class=brief>
 <li><p><var>byte</var> is less than 0x20 and is not 0x09 HT
 <li><p><var>byte</var> is 0x22 ("), 0x28 (left parenthesis), 0x29 (right parenthesis), 0x3A (:),
 0x3C (&lt;), 0x3E (>), 0x3F (?), 0x40 (@), 0x5B ([), 0x5C (\), 0x5D (]), 0x7B ({), 0x7D (}), or
 0x7F DEL.
 <!-- Delimiters from https://tools.ietf.org/html/rfc7230#section-3.2.6 except for ,/;= and
      including DEL -->
</ul>

<p>The <dfn noexport>CORS-unsafe request-header names</dfn>, given a <a for=/>header list</a>
<var>headers</var>, are determined as follows:

<ol>
 <li><p>Let <var>unsafeNames</var> be a new <a for=/>list</a>.

 <li><p>Let <var>potentiallyUnsafeNames</var> be a new <a for=/>list</a>.

 <li><p>Let <var>safelistValueSize</var> be 0.

 <li>
  <p><a for=list>For each</a> <var>header</var> of <var>headers</var>:

  <ol>
   <li><p>If <var>header</var> is not a <a>CORS-safelisted request-header</a>, then
   <a for=list>append</a> <var>header</var>'s <a for=header>name</a> to <var>unsafeNames</var>.

   <li><p>Otherwise, <a for=list>append</a> <var>header</var>'s <a for=header>name</a> to
   <var>potentiallyUnsafeNames</var> and increase <var>safelistValueSize</var> by
   <var>header</var>'s <a for=header>value</a>'s <a for="byte sequence">length</a>.
  </ol>

 <li><p>If <var>safelistValueSize</var> is greater than 1024, then <a for=list>for each</a>
 <var>name</var> of <var>potentiallyUnsafeNames</var>, <a for=list>append</a> <var>name</var> to
 <var>unsafeNames</var>.

 <li><p>Return the result of <a>convert header names to a sorted-lowercase set</a> with
 <var>unsafeNames</var>.
</ol>

<p>A <dfn export>CORS non-wildcard request-header name</dfn> is a <a>byte-case-insensitive</a> match
for `<code>Authorization</code>`.

<p>A <dfn export>privileged no-CORS request-header name</dfn> is a <a for=/>header</a>
<a for=header>name</a> that is a <a>byte-case-insensitive</a> match for one of

<ul class=brief>
 <li>`<code>Range</code>`.
</ul>

<div class="note no-backref">
 <p>These are headers that can be set by privileged APIs, and will be preserved if their associated
 request object is copied, but will be removed if the request is modified by unprivilaged APIs.

 <p>`<code>Range</code>` headers are commonly used by <a lt="downloads a hyperlink">downloads</a>
 and <a lt="resource fetch algorithm">media fetches</a>, although neither of these currently specify
 how. <a href=https://github.com/whatwg/html/pull/2814>html/2914</a> aims to solve this.

 <p>A helper is provided to <a for=request>add a range header</a> to a particular request.
</div>

<p>A <dfn export>CORS-safelisted response-header name</dfn>, given a
<a for=response>CORS-exposed header-name list</a> <var>list</var>, is a <a for=/>header</a>
<a for=header>name</a> that is a <a>byte-case-insensitive</a> match for one of

<ul class=brief>
 <li>`<code>Cache-Control</code>`
 <li>`<code>Content-Language</code>`
 <li>`<code>Content-Length</code>`
 <li>`<code>Content-Type</code>`
 <li>`<code>Expires</code>`
 <li>`<code>Last-Modified</code>`
 <li>`<code>Pragma</code>`
 <li>Any <a for=header>value</a> in <var>list</var> that is not a
 <a>forbidden response-header name</a>.
</ul>

<p>A <dfn noexport>no-CORS-safelisted request-header name</dfn> is a <a for=/>header</a>
<a for=header>name</a> that is a <a>byte-case-insensitive</a> match for one of

<ul class=brief>
 <li>`<code>Accept</code>`
 <li>`<code>Accept-Language</code>`
 <li>`<code>Content-Language</code>`
 <li>`<code>Content-Type</code>`
</ul>

<p>To determine whether a <a for/>header</a> <var>header</var> is a
<dfn noexport>no-CORS-safelisted request-header</dfn>, run these steps:

<ol>
 <li><p>If <var>header</var>'s <a for=header>name</a> is not a
 <a>no-CORS-safelisted request-header name</a>, then return false.

 <li><p>Return whether <var>header</var> is a <a>CORS-safelisted request-header</a>.
</ol>

<p>A <dfn export>forbidden header name</dfn> is a <a for=/>header</a> <a for=header>name</a> that
is a <a>byte-case-insensitive</a> match for one of

<ul class=brief>
 <li>`<code>Accept-Charset</code>`
 <li>`<code>Accept-Encoding</code>`
 <li>`<a http-header><code>Access-Control-Request-Headers</code></a>`
 <li>`<a http-header><code>Access-Control-Request-Method</code></a>`
 <li>`<code>Connection</code>`
 <li>`<code>Content-Length</code>`
 <li>`<code>Cookie</code>`
 <li>`<code>Cookie2</code>`
 <li>`<code>Date</code>`
 <li>`<code>DNT</code>`
 <li>`<code>Expect</code>`
 <li>`<code>Host</code>`
 <li>`<code>Keep-Alive</code>`
 <li>`<a http-header><code>Origin</code></a>`
 <li>`<code>Referer</code>`
 <li>`<code>TE</code>`
 <li>`<code>Trailer</code>`
 <li>`<code>Transfer-Encoding</code>`
 <li>`<code>Upgrade</code>`
 <li>`<code>Via</code>`
</ul>

<p>or a <a for=/>header</a> <a for=header>name</a> that
starts with a <a>byte-case-insensitive</a> match for `<code>Proxy-</code>` or `<code>Sec-</code>`
(including being a <a>byte-case-insensitive</a> match for just `<code>Proxy-</code>` or
`<code>Sec-</code>`).

<p class=note>These are forbidden so the user agent remains in full control over them.
<a for=header>Names</a> starting with `<code>Sec-</code>` are
reserved to allow new <a for=/>headers</a> to be minted that are safe
from APIs using <a for=/>fetch</a> that allow control over
<a for=/>headers</a> by developers, such as
{{XMLHttpRequest}}.
[[XHR]]

<p>A <dfn export>forbidden response-header name</dfn> is a <a for=/>header</a>
<a for=header>name</a> that is a <a>byte-case-insensitive</a> match for one of:

<ul class=brief>
 <li>`<code>Set-Cookie</code>`
 <li>`<code>Set-Cookie2</code>`
</ul>

<p>A <dfn export>request-body-header name</dfn> is a <a for=/>header</a> <a for=header>name</a> that
is a <a>byte-case-insensitive</a> match for one of:

<ul class=brief>
 <li>`<code>Content-Encoding</code>`
 <li>`<code>Content-Language</code>`
 <li>`<code>Content-Location</code>`
 <li>`<code>Content-Type</code>`
</ul>

<hr>

<p>To <dfn export lt="extract header values|extracting header values">extract header values</dfn>
given a <a for=/>header</a> <var>header</var>, run these steps:

<ol>
 <li><p>If parsing <var>header</var>'s <a for=header>value</a>, per the <a>ABNF</a> for
 <var>header</var>'s <a for=header>name</a>, fails, then return failure.

 <li><p>Return one or more <a for=header>values</a> resulting from parsing <var>header</var>'s
 <a for=header>value</a>, per the <a>ABNF</a> for <var>header</var>'s <a for=header>name</a>.
</ol>

<p>To
<dfn export lt="extract header list values|extracting header list values">extract header list values</dfn>
given a <a for=header>name</a> <var>name</var> and a <a for=/>header list</a> <var>list</var>,
run these steps:

<ol>
 <li><p>If <var>list</var> <a for="header list">does not contain</a> <var>name</var>, then return
 null.

 <li>
  <p>If the <a>ABNF</a> for <var>name</var> allows a single <a for=/>header</a> and <var>list</var>
  <a for="header list">contains</a> more than one, then return failure.

  <p class="note no-backref">If different error handling is needed, extract the desired
  <a for=/>header</a> first.

 <li><p>Let <var>values</var> be an empty <a for=/>list</a>.

 <li>
  <p>For each <a for=/>header</a> <var>header</var> <var>list</var>
  <a for="header list">contains</a> whose <a for=header>name</a> is <var>name</var>:

  <ol>
   <li><p>Let <var>extract</var> be the result of <a>extracting header values</a> from
   <var>header</var>.

   <li><p>If <var>extract</var> is failure, then return failure.

   <li><p>Append each <a for=header>value</a> in <var>extract</var>, in order, to <var>values</var>.
  </ol>

 <li><p>Return <var>values</var>.
</ol>

<hr>

<p>A <dfn id=default-user-agent-value export>default `<code>User-Agent</code>` value</dfn> is a
user-agent-defined <a for=header>value</a> for the
`<code>User-Agent</code>` <a for=/>header</a>.


<h4 id=statuses>Statuses</h4>

<p>A <dfn export id=concept-status>status</dfn> is a code.

<p>A <dfn export>null body status</dfn> is a <a for=/>status</a> that is <code>101</code>,
<code>204</code>, <code>205</code>, or <code>304</code>.

<p>An <dfn export>ok status</dfn> is any <a for=/>status</a> in the range <code>200</code> to
<code>299</code>, inclusive.

<p>A <dfn export>redirect status</dfn> is a <a for=/>status</a> that is <code>301</code>,
<code>302</code>, <code>303</code>, <code>307</code>, or <code>308</code>.


<h4 id=bodies>Bodies</h4>

<p>A <dfn export id=concept-body>body</dfn> consists of:

<ul>
 <li><p>A <dfn export for=body id=concept-body-stream>stream</dfn> (null or a {{ReadableStream}}
 object).

 <li><p>A <dfn export for=body id=concept-body-transmitted>transmitted bytes</dfn>
 (an integer), initially 0.

 <li><p>A <dfn export for=body id=concept-body-total-bytes>total bytes</dfn> (an
 integer), initially 0.

 <li><p>A <dfn export for=body id=concept-body-source>source</dfn>, initially null.
</ul>

<p>A <a for=/>body</a> <var>body</var> is said to be
<dfn export for=body id=concept-body-done>done</dfn> if <var>body</var> is null or
<var>body</var>'s <a for=body>stream</a> is
<a for=ReadableStream>closed</a> or
<a for=ReadableStream>errored</a>.

<p>To <dfn export for=body id=concept-body-wait>wait</dfn> for a
<a for=/>body</a> <var>body</var>, wait for <var>body</var> to be
<a for=body>done</a>.

<p>To <dfn export for=body id=concept-body-clone>clone</dfn> a
<a for=/>body</a> <var>body</var>, run these steps:

<ol>
 <li><p>Let «<var>out1</var>, <var>out2</var>» be the result of
 <a lt=tee for=ReadableStream>teeing</a> <var>body</var>'s <a for=body>stream</a>.

 <li><p>Set <var>body</var>'s <a for=body>stream</a> to <var>out1</var>.

 <li><p>Return a <a for=/>body</a> whose
 <a for=body>stream</a> is <var>out2</var> and other members are copied from
 <var>body</var>.
</ol>

<p>To <dfn export>handle content codings</dfn> given <var>codings</var> and <var>bytes</var>, run
these steps:

<ol>
 <li><p>If <var>codings</var> are not supported, then return <var>bytes</var>.

 <li><p>Return the result of decoding <var>bytes</var> with <var>codings</var> as explained in HTTP,
 if decoding does not result in an error, and failure otherwise. [[!HTTP]] [[!HTTP-SEMANTICS]]
</ol>
<!-- XXX https://github.com/whatwg/fetch/issues/716
         https://github.com/httpwg/http-core/issues/58 -->


<h4 id=requests>Requests</h4>

<p>The input to <a for=/>fetch</a> is a
<dfn export id=concept-request>request</dfn>.

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-method>method</dfn> (a
<a for=/>method</a>). Unless stated otherwise it is
`<code>GET</code>`.

<p class="note no-backref">This can be updated during redirects to `<code>GET</code>` as
described in <a>HTTP fetch</a>.

<p>A <a for=/>request</a> has an associated <dfn export for=request id=concept-request-url>URL</dfn>
(a <a for=/>URL</a>).

<p class="note no-backref">Implementations are encouraged to make this a pointer to the first
<a for=/>URL</a> in <a for=/>request</a>'s <a for=request>URL list</a>. It is provided as a distinct
field solely for the convenience of other standards hooking into Fetch.

<p>A <a for=/>request</a> has an associated
<dfn export>local-URLs-only flag</dfn>. Unless stated otherwise it is
unset.

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-header-list>header list</dfn> (a
<a for=/>header list</a>). Unless stated otherwise it is empty.

<p>A <a for=/>request</a> has an associated
<dfn id=unsafe-request-flag export for=request>unsafe-request flag</dfn>. Unless stated otherwise it
is unset.

<p class="note no-backref">The <a>unsafe-request flag</a> is set by APIs such as
<a><code>fetch()</code></a>  and
{{XMLHttpRequest}} to ensure a
<a>CORS-preflight fetch</a> is done based on the supplied
<a for=request>method</a> and
<a for=request>header list</a>. It does not free an API from
outlawing <a>forbidden methods</a> and
<a>forbidden header names</a>.

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-body>body</dfn> (null or a
<a for=/>body</a>). Unless stated otherwise it is null.

<p class="note no-backref">This can be updated during redirects to null as described in
<a>HTTP fetch</a>.

<hr>

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-client>client</dfn> (null or an
<a>environment settings object</a>).

<p>A <a for=/>request</a> has an associated
<dfn id=concept-request-reserved-client export for=request>reserved client</dfn>
(null, an <a for=/>environment</a>, or an
<a>environment settings object</a>). Unless stated otherwise it is null.

<p class="note no-backref">This is only used by <a>navigation requests</a> and worker
requests, but not service worker requests. It references an
<a for=/>environment</a> for a <a>navigation request</a> and an
<a>environment settings object</a> for a worker request.

<p>A <a for=/>request</a> has an associated
<dfn id=concept-request-replaces-client-id export for=request>replaces client id</dfn>
(a string). Unless stated otherwise it is the empty string.

<p class="note no-backref">This is only used by <a>navigation requests</a>. It is the
<a for="environment">id</a> of the
<a for="environment">target browsing context</a>'s
<a>active document</a>'s
<a>environment settings object</a>.

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-window>window</dfn>
("<code>no-window</code>", "<code>client</code>", or an
<a>environment settings object</a> whose
<a for="environment settings object">global object</a> is a
{{Window}} object). Unless stated otherwise it is
"<code>client</code>".

<p class="note no-backref">The "<code>client</code>" value is changed to "<code>no-window</code>" or
<a for=/>request</a>'s <a for=request>client</a> during
<a lt=fetch for=/>fetching</a>. It provides a convenient way for standards to not have to
explicitly set <a for=/>request</a>'s
<a for=request>window</a>.

<p id=keep-alive-flag>A <a for=/>request</a> has an associated
<dfn for=request export>keepalive flag</dfn>. Unless stated otherwise it is unset.

<p class="note no-backref">This can be used to allow the request to outlive the
<a>environment settings object</a>, e.g.,
<code>navigator.sendBeacon</code> and the HTML <code>img</code> element set this flag. Requests with
this flag set are subject to additional processing requirements.

<p>A <a for=/>request</a> has an associated <dfn for=request export>service-workers mode</dfn>, that
is "<code>all</code>" or "<code>none</code>". Unless stated otherwise it is "<code>all</code>".

<div class=note>
 <p>This determines which service workers will receive a {{fetch!!event}} event for this fetch.

 <dl>
  <dt>"<code>all</code>"
  <dd>Relevant service workers will get a {{fetch!!event}} event for this fetch.

  <dt>"<code>none</code>"
  <dd>No service workers will get events for this fetch.
 </dl>
</div>

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-initiator>initiator</dfn>, which is
the empty string,
"<code>download</code>",
"<code>imageset</code>",
"<code>manifest</code>",
"<code>prefetch</code>",
"<code>prerender</code>", or
"<code>xslt</code>". Unless stated otherwise it is the empty string.

<p class="note no-backref">A <a for=/>request</a>'s
<a for=request>initiator</a> is not particularly granular for
the time being as other specifications do not require it to be. It is primarily a
specification device to assist defining CSP and Mixed Content. It is not exposed to
JavaScript. [[!CSP]] [[!MIX]]

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-destination>destination</dfn>, which is
the empty string,
"<code>audio</code>",
"<code>audioworklet</code>",
"<code>document</code>",
"<code>embed</code>",
"<code>font</code>",
"<code>image</code>",
"<code>manifest</code>",
"<code>object</code>",
"<code>paintworklet</code>",
"<code>report</code>",
"<code>script</code>",
"<code>serviceworker</code>",
"<code>sharedworker</code>",
"<code>style</code>",
"<code>track</code>",
"<code>video</code>",
"<code>worker</code>", or
"<code>xslt</code>". Unless stated otherwise it is the empty string.

<!-- Dependencies:
     * CSP: https://w3c.github.io/webappsec-csp/#effective-directive-for-a-request
     * Mixed Content: https://w3c.github.io/webappsec-mixed-content/#should-block-fetch
     * Preload: https://w3c.github.io/preload/#processing
     * SRI: https://w3c.github.io/webappsec-subresource-integrity/#apply-algorithm-to-request
     * HTML -->

<p>A <a for=/>request</a>'s <a for=request>destination</a> is
<dfn export for=request/destination>script-like</dfn> if it is "<code>audioworklet</code>",
"<code>paintworklet</code>", "<code>script</code>", "<code>serviceworker</code>",
"<code>sharedworker</code>", or "<code>worker</code>".

<p class=warning>Algorithms that use <a for=request/destination>script-like</a> should also consider
"<code>xslt</code>" as that too can cause script execution. It is not included in the list as it is
not always relevant and might require different behavior.

<div class=note>
 <p>The following table illustrates the relationship between a <a for=/>request</a>'s
 <a for=request>initiator</a>, <a for=request>destination</a>, CSP directives, and features. It is
 not exhaustive with respect to features. Features need to have the relevant values defined in their
 respective standards.

 <table>
  <tbody><tr>
   <th><a lt=initiator for=request>Initiator</a>
   <th><a lt=destination for=request>Destination</a>
   <th>CSP directive
   <th>Features
  <tr>
   <td rowspan=18>""
   <td>"<code>report</code>"
   <td rowspan=2>&mdash;
   <td>CSP, NEL reports.
  <tr>
   <td>"<code>document</code>"
   <td>HTML's navigate algorithm.
  <tr>
   <td>"<code>document</code>"
   <td><code>child-src</code>
   <td>HTML's <code>&lt;iframe></code> and <code>&lt;frame></code>
  <tr>
   <td>""
   <td><code>connect-src</code>
   <td><code>navigator.sendBeacon()</code>, <code>EventSource</code>,
   HTML's <code>&lt;a ping=""></code> and <code>&lt;area ping=""></code>,
   <a><code>fetch()</code></a>, <code>XMLHttpRequest</code>, <code>WebSocket</code>, Cache API
  <tr>
   <td>"<code>object</code>"
   <td><code>object-src</code>
   <td>HTML's <code>&lt;object></code>
  <tr>
   <td>"<code>embed</code>"
   <td><code>object-src</code>
   <td>HTML's <code>&lt;embed></code>
  <tr>
   <td>"<code>audio</code>"
   <td><code>media-src</code>
   <td>HTML's <code>&lt;audio></code>
  <tr>
   <td>"<code>font</code>"
   <td><code>font-src</code>
   <td>CSS' <code>@font-face</code>
  <tr>
   <td>"<code>image</code>"
   <td><code>img-src</code>
   <td>HTML's <code>&lt;img src></code>, <code>/favicon.ico</code> resource,
   SVG's <code>&lt;image></code>, CSS' <code>background-image</code>, CSS'
   <code>cursor</code>, CSS' <code>list-style-image</code>, …
  <tr>
   <td>"<code>audioworklet</code>"
   <td><code>script-src</code>
   <td><code>audioWorklet.addModule()</code>
  <tr>
   <td>"<code>paintworklet</code>"
   <td><code>script-src</code>
   <td><code>CSS.paintWorklet.addModule()</code>
  <tr>
   <td>"<code>script</code>"
   <td><code>script-src</code>
   <td>HTML's <code>&lt;script></code>, <code>importScripts()</code>
  <tr>
   <td>"<code>serviceworker</code>"
   <td><code>child-src</code>, <code>script-src</code>, <code>worker-src</code>
   <td><code>navigator.serviceWorker.register()</code>
  <tr>
   <td>"<code>sharedworker</code>"
   <td><code>child-src</code>, <code>script-src</code>, <code>worker-src</code>
   <td><code>SharedWorker</code>
  <tr>
   <td>"<code>worker</code>"
   <td><code>child-src</code>, <code>script-src</code>, <code>worker-src</code>
   <td><code>Worker</code>
  <tr>
   <td>"<code>style</code>"
   <td><code>style-src</code>
   <td>HTML's <code>&lt;link rel=stylesheet></code>, CSS' <code>@import</code>
  <tr>
   <td>"<code>track</code>"
   <td><code>media-src</code>
   <td>HTML's <code>&lt;track></code>
  <tr>
   <td>"<code>video</code>"
   <td><code>media-src</code>
   <td>HTML's <code>&lt;video></code> element
  <tr>
   <td>"<code>download</code>"
   <td>""
   <td>&mdash;
   <td>HTML's <code>download=""</code>, "Save Link As…" UI
  <tr>
   <td>"<code>imageset</code>"
   <td>"<code>image</code>"
   <td><code>img-src</code>
   <td>HTML's <code>&lt;img srcset></code> and <code>&lt;picture></code>
  <tr>
   <td>"<code>manifest</code>"
   <td>"<code>manifest</code>"
   <td><code>manifest-src</code>
   <td>HTML's <code>&lt;link rel=manifest></code>
  <tr>
   <td>"<code>prefetch</code>"
   <td rowspan=2>""
   <td rowspan=2><code>prefetch-src</code>
   <td>HTML's <code>&lt;link rel=prefetch></code>
  <tr>
   <td>"<code>prerender</code>"
   <td>HTML's <code>&lt;link rel=prerender></code>
  <tr>
   <td>"<code>xslt</code>"
   <td>"<code>xslt</code>"
   <td><code>script-src</code>
   <td><code>&lt;?xml-stylesheet></code>
 </table>

 <p>CSP's <code>form-action</code> needs to be a hook directly in HTML's navigate or form
 submission algorithm.

 <p>CSP will also need to check
 <a for=/>request</a>'s
 <a for=request>client</a>'s
 <a for="environment settings object">responsible browsing context</a>'s
 <a>ancestor browsing contexts</a>
  for various CSP directives.
</div>

<hr>

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-priority>priority</dfn> (null or a
user-agent-defined object). Unless otherwise stated it is null.

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-origin>origin</dfn>, which is
"<code>client</code>" or an <a for=/>origin</a>. Unless stated otherwise it is
"<code>client</code>".

<p class="note no-backref">"<code>client</code>" is changed to an <a for=/>origin</a> during
<a lt=fetch for=/>fetching</a>. It provides a convenient way for standards to not have to set
<a for=/>request</a>'s <a for=request>origin</a>.

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-referrer>referrer</dfn>, which is
"<code>no-referrer</code>", "<code>client</code>", or a <a for=/>URL</a>. Unless stated otherwise it
is "<code>client</code>".

<p class="note no-backref">"<code>client</code>" is changed to "<code>no-referrer</code>" or a
<a for=/>URL</a> during <a lt=fetch for=/>fetching</a>. It provides a convenient way for standards
to not have to set <a for=/>request</a>'s <a for=request>referrer</a>.

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-referrer-policy>referrer policy</dfn>, which is a
<a for=/>referrer policy</a>. Unless stated otherwise it is the empty string. [[!REFERRER]]

<p class="note no-backref">This can be used to override a referrer policy associated with an
<a>environment settings object</a>.

<p>A <a for=/>request</a> has an associated
<dfn id=synchronous-flag export for=request>synchronous flag</dfn>. Unless stated otherwise it is
unset.

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-mode>mode</dfn>, which is
"<code>same-origin</code>", "<code>cors</code>", "<code>no-cors</code>",
"<code>navigate</code>", or "<code>websocket</code>". Unless stated otherwise, it is
"<code>no-cors</code>".

<div class="note no-backref">
 <dl>
  <dt>"<code>same-origin</code>"
  <dd>Used to ensure requests are made to same-origin URLs. <a for=/>Fetch</a> will return a
  <a>network error</a> if the request is not made to a same-origin URL.

  <dt>"<code>cors</code>"
  <dd>Makes the request a <a>CORS request</a>. Fetch will return a <a>network error</a> if the
  requested resource does not understand the <a>CORS protocol</a>.

  <dt>"<code>no-cors</code>"
  <dd>Restricts requests to using <a>CORS-safelisted methods</a> and
  <a>CORS-safelisted request-headers</a>. Upon success, fetch will return an
  <a>opaque filtered response</a>.

  <dt>"<code>navigate</code>"
  <dd>This is a special mode used only when <a>navigating</a> between documents.

  <dt>"<code>websocket</code>"
  <dd>This is a special mode used only when <a lt="establish a WebSocket connection">establishing
  a WebSocket connection</a>.
 </dl>

 <p>Even though the default <a for=/>request</a> <a for=request>mode</a> is "<code>no-cors</code>",
 standards are highly discouraged from using it for new features. It is rather unsafe.
</div>

<p>A <a for=/>request</a> has an associated
<dfn id=use-cors-preflight-flag export for=request>use-CORS-preflight flag</dfn>. Unless stated
otherwise, it is unset.

<p class="note no-backref">The <a>use-CORS-preflight flag</a> being set is one of several conditions
that results in a <a>CORS-preflight request</a>. The <a>use-CORS-preflight flag</a> is set if either
one or more event listeners are registered on an {{XMLHttpRequestUpload}} object or if a
{{ReadableStream}} object is used in a request.

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-credentials-mode>credentials mode</dfn>,
which is "<code>omit</code>", "<code>same-origin</code>", or
"<code>include</code>". Unless stated otherwise, it is "<code>omit</code>".

<div class="note no-backref">
 <dl>
  <dt>"<code>omit</code>"
  <dd>Excludes credentials from this request.

  <dt>"<code>same-origin</code>"
  <dd>Include credentials with requests made to same-origin URLs.

  <dt>"<code>include</code>"
  <dd>Always includes credentials with this request.
 </dl>

 <p><a for=/>Request</a>'s <a for=request>credentials mode</a> controls the flow of
 <a for=/>credentials</a> during a <a for=/>fetch</a>. When <a for=/>request</a>'s
 <a for=request>mode</a> is "<code>navigate</code>", its <a for=request>credentials mode</a> is
 assumed to be "<code>include</code>" and <a for=/>fetch</a> does not currently account for other
 values. If <cite>HTML</cite> changes here, this standard will need corresponding changes.
</div>

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-use-url-credentials-flag>use-URL-credentials flag</dfn>.
Unless stated otherwise, it is unset.

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-cache-mode>cache mode</dfn>, which is
"<code>default</code>", "<code>no-store</code>", "<code>reload</code>",
"<code>no-cache</code>", "<code>force-cache</code>", or
"<code>only-if-cached</code>". Unless stated otherwise, it is "<code>default</code>".

<div class="note no-backref">
 <dl>
  <dt>"<code>default</code>"
  <dd><a for=/>Fetch</a> will inspect the HTTP cache on the way to the network. If the HTTP cache
  contains a matching <a>fresh response</a> it will be returned. If the HTTP cache contains a
  matching <a>stale-while-revalidate response</a> it will be returned, and a conditional network
  fetch will be made to update the entry in the HTTP cache. If the HTTP cache contains a matching
  <a>stale response</a>, a conditional network fetch will be returned to update the entry in
  the HTTP cache. Otherwise, a non-conditional network fetch will be returned to update the entry
  in the HTTP cache. [[!HTTP]] [[!HTTP-SEMANTICS]] [[!HTTP-COND]] [[!HTTP-CACHING]] [[!HTTP-AUTH]]
  [[!STALE-WHILE-REVALIDATE]]

  <dt>"<code>no-store</code>"
  <dd>Fetch behaves as if there is no HTTP cache at all.

  <dt>"<code>reload</code>"
  <dd>Fetch behaves as if there is no HTTP cache on the way to the network. Ergo, it creates a
  normal request and updates the HTTP cache with the response.

  <dt>"<code>no-cache</code>"
  <dd>Fetch creates a conditional request if there is a response in the HTTP cache and a normal
  request otherwise. It then updates the HTTP cache with the response.

  <dt>"<code>force-cache</code>"
  <dd>Fetch uses any response in the HTTP cache matching the request, not paying attention to
  staleness. If there was no response, it creates a normal request and updates the HTTP cache with
  the response.

  <dt>"<code>only-if-cached</code>"
  <dd>Fetch uses any response in the HTTP cache matching the request, not paying attention to
  staleness. If there was no response, it returns a network error. (Can only be used when
  <a for=/>request</a>'s <a for=request>mode</a> is
  "<code>same-origin</code>". Any cached redirects will be followed assuming
  <a for=/>request</a>'s
  <a for=request>redirect mode</a> is "<code>follow</code>" and the
  redirects do not violate <a for=/>request</a>'s
  <a for=request>mode</a>.)
 </dl>

 <p>If <a for=request>header list</a> <a for="header list">contains</a>
 `<code>If-Modified-Since</code>`,
 `<code>If-None-Match</code>`,
 `<code>If-Unmodified-Since</code>`,
 `<code>If-Match</code>`, or
 `<code>If-Range</code>`,
 <a for=/>fetch</a> will set
 <a for=request>cache mode</a> to "<code>no-store</code>" if it is
 "<code>default</code>".
</div>

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-redirect-mode>redirect mode</dfn>, which is
"<code>follow</code>", "<code>error</code>", or "<code>manual</code>".
Unless stated otherwise, it is "<code>follow</code>".

<div class="note no-backref">
 <dl>
  <dt>"<code>follow</code>"
  <dd>Follow all redirects incurred when fetching a resource.

  <dt>"<code>error</code>"
  <dd>Return a <a>network error</a> when a request is met with a redirect.

  <dt>"<code>manual</code>"
  <dd>Retrieves an <a>opaque-redirect filtered response</a> when a request is met with a redirect so
  that the redirect can be followed manually.
 </dl>
</div>

<p>A <a for=/>request</a> has associated
<dfn export for=request id=concept-request-integrity-metadata>integrity metadata</dfn>
(a string). Unless stated otherwise, it is the empty string.

<p>A <a for=/>request</a> has associated
<dfn export for=request id=concept-request-nonce-metadata>cryptographic nonce metadata</dfn>
(a string). Unless stated otherwise, it is the empty string.

<p>A <a for=/>request</a> has associated
<dfn export for=request id=concept-request-parser-metadata>parser metadata</dfn>
which is the empty string, "<code>parser-inserted</code>", or
"<code>not-parser-inserted</code>". Unless otherwise stated, it is the empty string.

<p class="note no-backref">A <a for=/>request</a>'s <a for=request>cryptographic nonce metadata</a>
and <a for=request>parser metadata</a> are generally populated from attributes and flags on the HTML
element responsible for creating a <a for=/>request</a>. They are used by various algorithms in
<cite>Content Security Policy</cite> to determine whether requests or responses are to be blocked in
a given context. [[!CSP]]

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-reload-navigation-flag>reload-navigation flag</dfn>.
Unless stated otherwise, it is unset.

<p class="note no-backref">This flag is for exclusive use by HTML's navigate algorithm. [[!HTML]]

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-history-navigation-flag>history-navigation flag</dfn>.
Unless stated otherwise, it is unset.

<p class="note no-backref">This flag is for exclusive use by HTML's navigate algorithm. [[!HTML]]

<hr>

<p>A <a for=/>request</a> has an associated
<dfn for=request id=concept-request-tainted-origin>tainted origin flag</dfn>. Unless stated
otherwise, it is unset.

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-url-list>URL list</dfn> (a <a for=/>list</a> of one or
more <a for=/>URLs</a>). Unless stated otherwise, it is a list containing a copy of
<a for=/>request</a>'s <a for=request>URL</a>.

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-current-url>current URL</dfn>. It is a pointer to the
last <a for=/>URL</a> in <a for=/>request</a>'s <a for=request>URL list</a>.

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-redirect-count>redirect count</dfn>.
Unless stated otherwise, it is zero.

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=concept-request-response-tainting>response tainting</dfn>,
which is "<code>basic</code>", "<code>cors</code>", or "<code>opaque</code>".
Unless stated otherwise, it is "<code>basic</code>".

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=no-cache-prevent-cache-control>prevent no-cache cache-control header modification flag</dfn>.
Unless stated otherwise, it is unset.

<p>A <a for=/>request</a> has an associated <dfn export for=request id=done-flag>done flag</dfn>.
Unless stated otherwise, it is unset.

<p>A <a for=/>request</a> has an associated
<dfn export for=request id=timing-allow-failed>timing allow failed flag</dfn>. Unless stated
otherwise, it is unset.

<p class="note no-backref">A <a for=/>request</a>'s <a for=request>tainted origin flag</a>,
<a for=request>URL list</a>, <a for=request>current URL</a>, <a for=request>redirect count</a>,
<a for=request>response tainting</a>, <a for=request>done flag</a>, and
<a for=request>timing allow failed flag</a> are used as bookkeeping details by the
<a for=/>fetch</a> algorithm.

<hr>

<p>A <dfn export>subresource request</dfn> is a <a for=/>request</a>
whose <a for=request>destination</a> is "<code>audio</code>", "<code>audioworklet</code>",
"<code>font</code>", "<code>image</code>", "<code>manifest</code>", "<code>paintworklet</code>",
"<code>script</code>", "<code>style</code>", "<code>track</code>", "<code>video</code>",
"<code>xslt</code>", or the empty string.

<p>A <dfn export>potential-navigation-or-subresource request</dfn> is a
<a for=/>request</a> whose
<a for=request>destination</a> is
"<code>object</code>" or "<code>embed</code>".

<p>A <dfn export>non-subresource request</dfn> is a <a for=/>request</a>
whose <a for=request>destination</a> is "<code>document</code>",
"<code>report</code>", "<code>serviceworker</code>", "<code>sharedworker</code>",
or "<code>worker</code>".

<p>A <dfn export>navigation request</dfn> is a <a for=/>request</a> whose
<a for=request>destination</a> is
"<code>document</code>".

<p class=note>See <a for=/>handle fetch</a> for usage of these terms.
[[!SW]]

<hr>

<p><dfn>Serializing a request origin</dfn>, given a <a for=/>request</a> <var>request</var>, is to
run these steps:

<ol>
 <li><p>If <var>request</var>'s <a for=request>tainted origin flag</a> is set, then return
 "<code>null</code>".

 <li><p>Return <var>request</var>'s <a for=request>origin</a>,
 <a lt="ASCII serialization of an origin">serialized</a>.
</ol>

<p><dfn>Byte-serializing a request origin</dfn>, given a <a for=/>request</a> <var>request</var>,
is to return the result of <a>serializing a request origin</a> with <var>request</var>,
<a>isomorphic encoded</a>.

<hr>

<p>To <dfn export for=request id=concept-request-clone>clone</dfn> a
<a for=/>request</a> <var>request</var>, run these steps:

<ol>
 <li><p>Let <var>newRequest</var> be a copy of <var>request</var>, except for its
 <a for=request>body</a>.

 <li><p>If <var>request</var>'s <a for=request>body</a> is non-null, set <var>newRequest</var>'s
 <a for=request>body</a> to the result of <a lt=clone for=body>cloning</a> <var>request</var>'s
 <a for=request>body</a>.

 <li><p>Return <var>newRequest</var>.
</ol>

<hr>

<p>To <dfn export for=request id=concept-request-transmit-body>transmit body</dfn> for a
<a for=/>request</a> <var>request</var>, run these steps:

<ol>
 <li>Let <var>body</var> be <var>request</var>'s <a for=request>body</a>.

 <li><p>If <var>body</var> is null, then <a>queue a fetch task</a> on <var>request</var> to
 <a>process request end-of-body</a> for <var>request</var> and abort these steps.

 <li>
  <p>Let <var>reader</var> be the result of <a lt="get a reader" for=ReadableStream>getting
  a reader</a> from <var>body</var>'s <a for=body>stream</a>.

  <p class="note no-backref">This operation cannot throw an exception.

 <li><p>Let <var>read</var> be the result of <a lt="read a chunk" for=ReadableStream>reading a
 chunk</a> from <var>body</var>'s <a for=body>stream</a> with <var>reader</var>.

 <li>
  <p><a>In parallel</a>, while true:

  <ol>
   <li>
    <p>Run these steps, but <a>abort when</a> the ongoing fetch is <a for=fetch>terminated</a>:

    <ol>
     <li><p>Wait for <var>read</var> to be fulfilled or rejected.

     <li>
      <p>If <var>read</var> is fulfilled with an object whose <code>done</code> property is false
      and whose <code>value</code> property is a <code>Uint8Array</code> object, then run these
      steps:

      <ol>
       <li><p>Let <var>bs</var> be the <a>byte sequence</a> represented by the
       <code>Uint8Array</code> object.

       <li>
        <p>Transmit <var>bs</var>. Whenever one or more bytes are transmitted, increase
        <var>body</var>'s <a for=body>transmitted bytes</a> by the number of transmitted bytes and
        <a>queue a fetch task</a> on <var>request</var> to <a>process request body</a>
        for <var>request</var>.

        <p class="note no-backref">This step blocks until <var>bs</var> is fully transmitted.

       <li><p>Set <var>read</var> to the result of <a lt="read a chunk" for=ReadableStream>reading a
       chunk</a> from <var>body</var>'s <a for=body>stream</a> with <var>reader</var>.
      </ol>

     <li><p>Otherwise, if <var>read</var> is fulfilled with an object whose <code>done</code>
     property is true, then <a>queue a fetch task</a> on <var>request</var> to
     <a>process request end-of-body</a> for <var>request</var> and abort these in-parallel steps.

     <li><p>Otherwise, if <var>read</var> is rejected with an
     "<code><a exception>AbortError</a></code>" {{DOMException}},
     <a lt=terminated for=fetch>terminate</a> the ongoing fetch with the aborted flag set.

     <li><p>Otherwise, <a lt=terminated for=fetch>terminate</a> the ongoing fetch.
    </ol>

   <li><p><a>If aborted</a>, then abort these in-parallel steps.
  </ol>
</ol>

<hr>

<p>To <dfn export for=request id=concept-request-add-range-header>add a range header</dfn> to a
<a for=/>request</a> <var>request</var>, with an integer <var>first</var>, and an optional integer
<var>last</var>, run these steps:

<ol>
 <li><p>Let <var>rangeValue</var> be `<code>bytes </code>`.

 <li><p><a lt="serialize an integer">Serialize</a> and <a>isomorphic encode</a> <var>first</var>,
 and append the result to <var>rangeValue</var>.

 <li><p>Append 0x2D (-) to <var>rangeValue</var>.

 <li><p>If <var>last</var> is given, then <a lt="serialize an integer">serialize</a> and
 <a>isomorphic encode</a> it, and append the result to <var>rangeValue</var>.

 <li><p><a for="header list">Append</a> `<code>Range</code>`/<var>rangeValue</var> to
 <var>request</var>'s <a for=request>header list</a>.
</ol>

<p class=note>A range header denotes an inclusive byte range. There a range header where
<var>first</var> is 0 and <var>last</var> is 500, is a range of 501 bytes.

<p class=note>Features that combine multiple responses into one logical resource are historically a
source of security bugs. Please seek security review for features that deal with partial responses.


<h4 id=responses>Responses</h4>

<p>The result of <a for=/>fetch</a> is a
<dfn export id=concept-response>response</dfn>. A <a for=/>response</a>
evolves over time. That is, not all its fields are available straight away.

<p>A <a for=/>response</a> has an associated
<dfn export for=response id=concept-response-type>type</dfn> which is
"<code>basic</code>",
"<code>cors</code>",
"<code>default</code>",
"<code>error</code>",
"<code>opaque</code>", or
"<code>opaqueredirect</code>".
Unless stated otherwise, it is "<code>default</code>".

<p>A <a for=/>response</a> can have an associated
<dfn export for=response id=concept-response-aborted>aborted flag</dfn>, which is initially unset.

<p class="note">This indicates that the request was intentionally aborted by the developer or
end-user.

<p>A <a for=/>response</a> has an associated
<dfn export for=response id=concept-response-url>URL</dfn>. It is a pointer to the last
<a>response URL</a> in <a for=/>response</a>'s <a for=response>URL list</a> and null if
<a for=/>response</a>'s <a for=response>URL list</a> is the empty list.

<p>A <a for=/>response</a> has an associated
<dfn export for=response id=concept-response-url-list>URL list</dfn> (a <a for=/>list</a> of zero or
more <a>response URLs</a>). Unless stated otherwise, it is the empty list.

<p class="note no-backref">Except for the last <a>response URL</a>, if any, a
<a for=/>response</a>'s <a for=response>URL list</a> cannot be exposed to script. That would violate
<a>atomic HTTP redirect handling</a>.

<p>A <a for=/>response</a> has an associated
<dfn export for=response id=concept-response-status>status</dfn>, which is a
<a for=/>status</a>. Unless stated otherwise it is <code>200</code>.

<p>A <a for=/>response</a> has an associated
<dfn export for=response id=concept-response-status-message>status message</dfn>. Unless stated
otherwise it is the empty byte sequence.

<p class=note>Responses over an HTTP/2 connection will always have the empty byte sequence as status
message as HTTP/2 does not support them.

<p>A <a for=/>response</a> has an associated
<dfn export for=response id=concept-response-header-list>header list</dfn> (a
<a for=/>header list</a>). Unless stated otherwise it is empty.

<p>A <a for=/>response</a> has an associated
<dfn export for=response id=concept-response-body>body</dfn> (null or a
<a for=/>body</a>). Unless stated otherwise it is null.

<p>A <a for=/>response</a> has an associated
<dfn export for=response id=concept-response-cache-state>cache state</dfn> (the empty string or
"<code>local</code>"). Unlesss stated otherwise, it is the empty string.

<p class=note>This is intended solely for usage by service workers. [[SW]]
<!-- If we ever expand the utility of this we need to carefully consider whether filtered responses
     need to mask it, whether the cache API needs to store it, etc. -->

<p>A <a for=/>response</a> has an associated
<dfn export for=response id=concept-response-https-state>HTTPS state</dfn> (an
<a>HTTPS state value</a>). Unless stated otherwise, it is
"<code>none</code>".

<p>A <a for=/>response</a> has an associated
<dfn export for=response id=concept-response-csp-list>CSP list</dfn>, which is a
list of <a href=https://w3c.github.io/webappsec-csp/#policy>Content Security Policy objects</a>
for the <a for=/>response</a>. The list is empty unless otherwise
specified. [[!CSP]]

<p>A <a for=/>response</a> has an associated
<dfn export for=response id=concept-response-cors-exposed-header-name-list>CORS-exposed header-name list</dfn>
(a list of zero or more <a for=/>header</a>
<a lt=name for=header>names</a>). The list is empty unless otherwise specified.

<p class="note no-backref">A <a for=/>response</a> will typically get its
<a for=response>CORS-exposed header-name list</a> set by <a>extracting header values</a> from the
`<a http-header><code>Access-Control-Expose-Headers</code></a>` header. This list is used by a
<a>CORS filtered response</a> to determine which headers to expose.

<p>A <a for=/>response</a> has an associated
<dfn for=response id=concept-response-range-requested-flag>range-requested flag</dfn>, which is
initially unset.

<p class=note>This is used to ensure to prevent a partial response from an earlier ranged request
being provided to an API that didn't make a range request. See the flag's usage for a detailed
description of the attack.

<p>A <a for=/>response</a> has an associated
<dfn for=response id=concept-response-timing-allow-passed>timing allow passed flag</dfn>, which is
initially unset.

<p class=note>This is used so that the caller to a fetch can determine if sensitive timing data is
allowed on the resource fetched by looking at the flag of the response returned. Because the flag on
the response of a redirect has to be set if it was set for previous responses in the redirect chain,
this is also tracked internally using the request's <a for=request>timing allow failed flag</a>.

<p>A <a for=/>response</a> can have an associated
<dfn export for=response id=concept-response-location-url>location URL</dfn> (null, failure, or a
<a for=/>URL</a>). Unless specified otherwise, <a for=/>response</a> has no
<a for=response>location URL</a>.

<p class="note no-backref">This concept is used for redirect handling in Fetch and in HTML's
navigate algorithm. It ensures `<code>Location</code>` has
<a lt="extracting header values">its value extracted</a> consistently and only once.
[[!HTML]]

<hr>

<p>A <a for=/>response</a> whose
<a for=response>type</a> is "<code>error</code>" and <a for=response>aborted flag</a> is set is
known as an <dfn export id=concept-aborted-network-error>aborted network error</dfn>.

<p>A <a for=/>response</a> whose
<a for=response>type</a> is "<code>error</code>" is known as a
<dfn export id=concept-network-error>network error</dfn>.

<p>A <a>network error</a> is a
<a for=/>response</a> whose
<a for=response>status</a> is always <code>0</code>,
<a for=response>status message</a> is always the empty byte sequence,
<a for=response>header list</a> is always empty, and
<a for=response>body</a> is always null.

<hr>

<p>A <dfn export id=concept-filtered-response>filtered response</dfn> is a limited view on a
<a for=/>response</a> that is not a
<a>network error</a>. This
<a for=/>response</a> is referred to as the
<a>filtered response</a>'s associated
<dfn export id=concept-internal-response for=internal>internal response</dfn>.

<p class="note no-backref">The <a for=/>fetch</a> algorithm returns such a view to ensure APIs do
not accidentally leak information. If the information needs to be exposed for legacy reasons, e.g.,
to feed image data to a decoder, the associated <a for=internal>internal response</a> can be used,
which is only "accessible" to internal specification algorithms and is never a
<a>filtered response</a> itself.

<p>A <dfn export id=concept-filtered-response-basic>basic filtered response</dfn> is a
<a>filtered response</a> whose
<a for=response>type</a> is "<code>basic</code>" and
<a for=response>header list</a> excludes any
<a for=/>headers</a> in
<a for=internal>internal response</a>'s
<a for=response>header list</a> whose
<a for=header>name</a> is a
<a>forbidden response-header name</a>.

<p>A <dfn export id=concept-filtered-response-cors>CORS filtered response</dfn> is a
<a>filtered response</a> whose
<a for=response>type</a> is "<code>cors</code>" and
<a for=response>header list</a> excludes any
<a for=/>headers</a> in
<a for=internal>internal response</a>'s
<a for=response>header list</a> whose
<a for=header>name</a> is <em>not</em> a
<a>CORS-safelisted response-header name</a>, given
<a for=internal>internal response</a>'s
<a for=response>CORS-exposed header-name list</a>.

<p>An <dfn export id=concept-filtered-response-opaque>opaque filtered response</dfn> is a
<a>filtered response</a> whose
<a for=response>type</a> is "<code>opaque</code>",
<a for=response>URL list</a> is the empty list,
<a for=response>status</a> is <code>0</code>,
<a for=response>status message</a> is the empty byte sequence,
<a for=response>header list</a> is empty, and
<a for=response>body</a> is null.

<p>An
<dfn export id=concept-filtered-response-opaque-redirect>opaque-redirect filtered response</dfn>
is a <a>filtered response</a> whose
<a for=response>type</a> is "<code>opaqueredirect</code>",
<a for=response>status</a> is <code>0</code>,
<a for=response>status message</a> is the empty byte sequence,
<a for=response>header list</a> is empty, and
<a for=response>body</a> is null.

<div class="note no-backref">
 <p>Exposing the <a for=response>URL list</a> for
 <a lt="opaque-redirect filtered response">opaque-redirect filtered responses</a> is harmless since
 no redirects are followed.

 <p>In other words, an <a>opaque filtered response</a>
 and an
 <a>opaque-redirect filtered response</a> are
 nearly indistinguishable from a <a>network error</a>. When
 introducing new APIs, do not use the <a for=internal>internal response</a>
 for internal specification algorithms as that will leak information.

 <p>This also means that JavaScript APIs, such as <a attribute for=Response lt=ok><code>response.ok</code></a>,
 will return rather useless results.
</div>

<p>To <dfn export for=response id=concept-response-clone>clone</dfn> a
<a for=/>response</a> <var>response</var>, run these steps:

<ol>
 <li><p>If <var>response</var> is a <a>filtered response</a>, then return a new identical filtered
 response whose <a lt="internal response" for=internal>internal response</a> is a
 <a for=response>clone</a> of <var>response</var>'s <a for=internal>internal response</a>.

 <li><p>Let <var>newResponse</var> be a copy of <var>response</var>, except for its
 <a for=response>body</a>.

 <li><p>If <var>response</var>'s <a for=response>body</a> is non-null, then set
 <var>newResponse</var>'s <a for=response>body</a> to the result of <a lt=clone for=body>cloning</a>
 <var>response</var>'s <a for=response>body</a>.

 <li><p>Return <var>newResponse</var>.
</ol>

<p>A <dfn id=concept-fresh-response>fresh response</dfn> is a <a for=/>response</a> whose
<a href=https://tools.ietf.org/html/rfc7234#section-4.2.3>current age</a> is within its
<a href=https://tools.ietf.org/html/rfc7234#section-4.2.1>freshness lifetime</a>.

<p>A <dfn id=concept-stale-while-revalidate-response>stale-while-revalidate response</dfn> is a
<a for=/>response</a> that is not a <a>fresh response</a> and whose
<a href=https://tools.ietf.org/html/rfc7234#section-4.2.3>current age</a> is within the
<a href=https://tools.ietf.org/html/rfc5861#section-3>stale-while-revalidate lifetime</a>.

<p>A <dfn export id=concept-stale-response>stale response</dfn> is a <a for=/>response</a> is a
<a for=/>response</a> that is not a <a>fresh response</a> or a
<a>stale-while-revalidate response</a>.


<h4 id=miscellaneous>Miscellaneous</h4>

<p>A <dfn export id=concept-potential-destination>potential destination</dfn> is
"<code>fetch</code>" or a <a for=request>destination</a> which is not the empty string.

<p>To <dfn export for=destination id=concept-potential-destination-translate>translate</dfn> a
<a for=/>potential destination</a> <var>potentialDestination</var>, run these steps:

<ol>
 <li><p>If <var>potentialDestination</var> is "<code>fetch</code>", then return the empty string.

 <li><p>Assert: <var>potentialDestination</var> is a <a for=request>destination</a>.

 <li><p>Return <var>potentialDestination</var>.
</ol>


<h3 id=authentication-entries>Authentication entries</h3>

<p>An <dfn export>authentication entry</dfn> and a <dfn export>proxy-authentication entry</dfn> are
tuples of username, password, and realm, used for HTTP authentication and HTTP proxy authentication,
and associated with one or more <a for=/>requests</a>.
<p>User agents should allow both to be cleared together with HTTP cookies and similar tracking
functionality.
<!-- fingerprinting -->

<p>Further details are defined by HTTP. [[!HTTP]] [[!HTTP-SEMANTICS]] [[!HTTP-COND]] [[!HTTP-CACHING]] [[!HTTP-AUTH]]


<h3 id=fetch-groups>Fetch groups</h3>

<p>Each <a>environment settings object</a> has an associated
<dfn export id=concept-fetch-group for=fetch>fetch group</dfn>.

<p>A <a for=fetch>fetch group</a> holds an ordered list of
<dfn lt="fetch record" export for="fetch group" id=concept-fetch-record>fetch records</dfn>.

<p>A <a for="fetch group">fetch record</a> has an associated
<dfn export for="fetch record" id=concept-fetch-record-request>request</dfn> (a
<a for=/>request</a>).

<p>A <a for="fetch group">fetch record</a> has an associated
<dfn export for="fetch record" id=concept-fetch-record-fetch>fetch</dfn> (a
<a for=/>fetch</a> algorithm or null).

<hr>

<p>When a <a for=fetch>fetch group</a> is
<dfn export for="fetch group" id=concept-fetch-group-terminate>terminated</dfn>,
for each associated <a for="fetch group">fetch record</a> whose
<a for="fetch record">request</a>'s <a>done flag</a> or
<a>keepalive flag</a> is unset,
<a lt=terminated for=fetch>terminate</a> the
<a for="fetch group">fetch record</a>'s
<a for="fetch record">fetch</a>.


<h3 id=connections>Connections</h3>

<p>A user agent has an associated
<dfn export id=concept-connection-pool for=connection>connection pool</dfn>. A
<a for=connection>connection pool</a> consists of zero or more
<dfn lt=connection export id=concept-connection>connections</dfn>. Each
<a>connection</a> is identified by an <b>origin</b> (an
<a for=/>origin</a>) and <b>credentials</b> (a boolean).

<p>To <dfn export id=concept-connection-obtain for=connection>obtain a connection</dfn>, given an
<var>origin</var> and <var>credentials</var>, run these steps:

<ol>
 <li><p>If <a for=connection>connection pool</a> contains a <a>connection</a> whose <b>origin</b> is
 <var>origin</var> and <b>credentials</b> is <var>credentials</var>, then return that
 <a>connection</a>.

 <li><p>Let <var>connection</var> be null.

 <li>
  <p>Run these steps, but <a>abort when</a> the ongoing fetch is <a for=fetch>terminated</a>:

  <ol>
   <li>
    <p>Set <var>connection</var> to the result of establishing an HTTP connection to
    <var>origin</var>. [[!HTTP]] [[!HTTP-SEMANTICS]] [[!HTTP-COND]] [[!HTTP-CACHING]] [[!HTTP-AUTH]]
    [[!TLS]]

    <p>If <var>credentials</var> is false, then do <em>not</em> send a TLS client certificate.

    <p>If establishing a connection does not succeed (e.g., a DNS, TCP, or TLS error), then return
    failure.
  </ol>

 <li>
  <p><a>If aborted</a>, then:

  <ol>
   <li><p>If <var>connection</var> is not null, then close <var>connection</var>.

   <li><p>Return failure.
  </ol>

 <li><p>Add <var>connection</var> to the <a for=connection>connection pool</a> with <b>origin</b>
 being <var>origin</var> and <b>credentials</b> being <var>credentials</var>.

 <li><p>Return <var>connection</var>.
</ol>

<p class="note no-backref">This is intentionally a little vague as the finer points are still
evolving. Describing this helps explain the <code>&lt;link rel=preconnect></code> feature and
clearly stipulates that <a>connections</a> are keyed on
<b>credentials</b>. The latter clarifies that e.g., TLS session identifiers are not reused across
<a>connections</a> whose <b>credentials</b> are false with
<a>connections</a> whose <b>credentials</b> are true.
<!-- See https://github.com/whatwg/fetch/issues/114#issuecomment-143500095 for when we make
     WebSocket saner -->


<h3 id=port-blocking>Port blocking</h3>

<p>To determine whether fetching a <a for=/>request</a> <var>request</var>
<dfn export lt="block bad port">should be blocked due to a bad port</dfn>,
run these steps:

<ol>
 <li><p>Let <var>url</var> be <var>request</var>'s
 <a for=request>current URL</a>.

 <li><p>Let <var>scheme</var> be <var>url</var>'s
 <a for=url>scheme</a>.

 <li><p>Let <var>port</var> be <var>url</var>'s
 <a for=url>port</a>.

 <li><p>If <var>scheme</var> is "<code>ftp</code>" and <var>port</var> is 20 or 21, then
 return <b>allowed</b>.

 <li><p>Otherwise, if <var>scheme</var> is a <a>network scheme</a> and
 <var>port</var> is a <a>bad port</a>, then return <b>blocked</b>.

 <li><p>Return <b>allowed</b>.
</ol>

<p>A <a for=url>port</a> is a
<dfn export>bad port</dfn> if it is listed in the first column of the following table.

<table>
 <tbody><tr><th>Port<th>Typical service
 <tr><td>1<td>tcpmux
 <tr><td>7<td>echo
 <tr><td>9<td>discard
 <tr><td>11<td>systat
 <tr><td>13<td>daytime
 <tr><td>15<td>netstat
 <tr><td>17<td>qotd
 <tr><td>19<td>chargen
 <tr><td>20<td>ftp-data
 <tr><td>21<td>ftp
 <tr><td>22<td>ssh
 <tr><td>23<td>telnet
 <tr><td>25<td>smtp
 <tr><td>37<td>time
 <tr><td>42<td>name
 <tr><td>43<td>nicname
 <tr><td>53<td>domain
 <tr><td>77<td>priv-rjs
 <tr><td>79<td>finger
 <tr><td>87<td>ttylink
 <tr><td>95<td>supdup
 <tr><td>101<td>hostriame
 <tr><td>102<td>iso-tsap
 <tr><td>103<td>gppitnp
 <tr><td>104<td>acr-nema
 <tr><td>109<td>pop2
 <tr><td>110<td>pop3
 <tr><td>111<td>sunrpc
 <tr><td>113<td>auth
 <tr><td>115<td>sftp
 <tr><td>117<td>uucp-path
 <tr><td>119<td>nntp
 <tr><td>123<td>ntp
 <tr><td>135<td>loc-srv / epmap
 <tr><td>139<td>netbios
 <tr><td>143<td>imap2
 <tr><td>179<td>bgp
 <tr><td>389<td>ldap
 <tr><td>427<td>afp (alternate)
 <tr><td>465<td>smtp (alternate)
 <tr><td>512<td>print / exec
 <tr><td>513<td>login
 <tr><td>514<td>shell
 <tr><td>515<td>printer
 <tr><td>526<td>tempo
 <tr><td>530<td>courier
 <tr><td>531<td>chat
 <tr><td>532<td>netnews
 <tr><td>540<td>uucp
 <tr><td>548<td>afp
 <tr><td>556<td>remotefs
 <tr><td>563<td>nntp+ssl
 <tr><td>587<td>smtp (outgoing)
 <tr><td>601<td>syslog-conn
 <tr><td>636<td>ldap+ssl
 <tr><td>993<td>ldap+ssl
 <tr><td>995<td>pop3+ssl
 <tr><td>2049<td>nfs
 <tr><td>3659<td>apple-sasl
 <tr><td>4045<td>lockd
 <tr><td>6000<td>x11
 <tr><td>6665<td>irc (alternate)
 <tr><td>6666<td>irc (alternate)
 <tr><td>6667<td>irc (default)
 <tr><td>6668<td>irc (alternate)
 <tr><td>6669<td>irc (alternate)
 <tr><td>6697<td>irc+tls
</table>
<!-- https://www-archive.mozilla.org/projects/netlib/PortBanning.html -->


<h3 dfn export lt="should response to request be blocked due to mime type" id=should-response-to-request-be-blocked-due-to-mime-type?>Should
<var>response</var> to <var>request</var> be blocked due to its MIME type?</h3>

<p>Run these steps:

<ol>
 <li><p>Let <var>mimeType</var> be the result of <a for="header list">extracting a MIME type</a>
 from <var>response</var>'s <a for=response>header list</a>.

 <li><p>If <var>mimeType</var> is failure, then return <b>allowed</b>.

 <li><p>Let <var>destination</var> be <var>request</var>'s <a for=request>destination</a>.

 <li>
  <p>If <var>destination</var> is <a for=request/destination>script-like</a> and one of the
  following is true, then return <b>blocked</b>:

  <ul class=brief>
   <li><var>mimeType</var>'s <a for="MIME type">essence</a> starts with "<code>audio/</code>",
   "<code>image/</code>", or "<code>video/</code>".
   <li><var>mimeType</var>'s <a for="MIME type">essence</a> is "<code>text/csv</code>".
  </ul>

 <li><p>Return <b>allowed</b>.
</ol>


<h3 id=streams>Streams</h3>

<p class="note no-backref">This section might be integrated into other standards, such as IDL.


<h4 id=readablestream>ReadableStream</h4>

<p>A <dfn export interface id=concept-readablestream><code>ReadableStream</code></dfn> object
represents a <a href=https://streams.spec.whatwg.org/#rs-class>stream of data</a>. In this section,
we define common operations for {{ReadableStream}} objects. [[!STREAMS]]

<p>To <dfn export for=ReadableStream id=concept-enqueue-readablestream>enqueue</dfn>
<var>chunk</var> into a {{ReadableStream}} object <var>stream</var>, run these steps:

<ol>
 <li><p>Call
 <a abstract-op>ReadableStreamDefaultControllerEnqueue</a>(<var>stream</var>.\[[readableStreamController]],
 <var>chunk</var>).
</ol>

<p>To <dfn abstract-op export for=ReadableStream id=concept-close-readablestream>close</dfn> a
{{ReadableStream}} object <var>stream</var>, run these steps:

<ol>
 <li><p>Call
 <a abstract-op>ReadableStreamDefaultControllerClose</a>(<var>stream</var>.\[[readableStreamController]]).
</ol>

<p>To <dfn abstract-op export for=ReadableStream id=concept-error-readablestream>error</dfn> a
{{ReadableStream}} object <var>stream</var> with given <var>reason</var>, run these steps:

<ol>
 <li><p>Call
 <a abstract-op>ReadableStreamDefaultControllerError</a>(<var>stream</var>.\[[readableStreamController]]).
 <var>reason</var>).
</ol>

<p>To
<dfn export for=ReadableStream id=concept-construct-readablestream>construct a <code>ReadableStream</code> object</dfn>
optionally with a <var>highWaterMark</var>, <var>sizeAlgorithm</var> algorithm, <var>pull</var>
action, and <var>cancel</var> action, run these steps:

<p class=note>This algorithm used to take a <var ignore>strategy</var> parameter, whose
<code>highWaterMark</code> and <code>sizeAlgorithm</code> members were extracted to provide what are
now separate parameters. If another specification still passes that <var ignore>strategy</var>
parameter, please update it.

<ol>
 <li><p>Let <var>startAlgorithm</var> be an algorithm that returns undefined.

 <li><p>If <var>pull</var> is not given, then set it to an action that does nothing.

 <li>
  <p>Let <var>pullAlgorithm</var> be an algorithm that runs these steps:

  <ol>
   <li><p>Run <var>pull</var>.

   <li><p>Return <a>a promise resolved with</a> undefined.
  </ol>

 <li><p>If <var>cancel</var> is not given, then set it to an action that does nothing.

 <li>
  <p>Let <var>cancelAlgorithm</var> be an algorithm that runs these steps:

  <ol>
   <li><p>Run <var>cancel</var>.

   <li><p>Return <a>a promise resolved with</a> undefined.
  </ol>

 <li><p>If <var>highWaterMark</var> is not given, then set it to 1.

 <li><p>If <var>sizeAlgorithm</var> is not given, then set it to an algorithm that returns 1.

 <li><p>Return [$CreateReadableStream$](<var>startAlgorithm</var>, <var>pullAlgorithm</var>,
 <var>cancelAlgorithm</var>, <var>highWaterMark</var>, <var>sizeAlgorithm</var>).
</ol>

<p>To
<dfn export for=ReadableStream id=concept-construct-fixed-readablestream>construct a fixed <code>ReadableStream</code> object</dfn>
with given <var>chunks</var>, run these steps:

<ol>
 <li><p>Let <var>stream</var> be the result of
 <a lt="construct a ReadableStream object" for=ReadableStream>constructing</a> a {{ReadableStream}}
 object.

 <li><p>For each <var>chunk</var> in <var>chunks</var>, <a for=ReadableStream>enqueue</a>
 <var>chunk</var> into <var>stream</var>.

 <li><p><a lt=close abstract-op>Close</a> <var>stream</var>.

 <li>Return <var>stream</var>.
</ol>

<p>To <dfn export for=ReadableStream id=concept-get-reader>get a reader</dfn> from a
{{ReadableStream}} object <var>stream</var>, run these steps:

<ol>
 <li><p>Let <var>reader</var> be the result of calling
 <a abstract-op>AcquireReadableStreamDefaultReader</a>(<var>stream</var>).

 <li><p>Return <var>reader</var>.
</ol>

<p>To
<dfn export for=ReadableStream id=concept-read-chunk-from-readablestream>read a chunk</dfn> from a
{{ReadableStream}} object with <var>reader</var>, return the result of calling
<a abstract-op>ReadableStreamDefaultReaderRead</a>(<var>reader</var>).

<p>To
<dfn export for=ReadableStream id=concept-read-all-bytes-from-readablestream>read all bytes</dfn>
from a {{ReadableStream}} object with <var>reader</var>, run these steps:

<ol>
 <li><p>Let <var>promise</var> be a new promise.

 <li><p>Let <var>bytes</var> be an empty byte sequence.

 <li>
 <p>Let <var>read</var> be the result of calling
 <a abstract-op>ReadableStreamDefaultReaderRead</a>(<var>reader</var>).

 <ul>
  <li><p>When <var>read</var> is fulfilled with an object whose <code>done</code>
  property is false and whose <code>value</code> property is a
  <code>Uint8Array</code> object, append the <code>value</code> property to
  <var>bytes</var> and run the above step again.

  <li><p>When <var>read</var> is fulfilled with an object whose <code>done</code>
  property is true, resolve <var>promise</var> with <var>bytes</var>.

  <li><p>When <var>read</var> is fulfilled with a value that matches with neither of the
  above patterns, reject <var>promise</var> with a {{TypeError}}.

  <li><p>When <var>read</var> is rejected with an error, reject <var>promise</var>
  with that error.
 </ul>

 <li><p>Return <var>promise</var>.
</ol>

<p>To <dfn export for=ReadableStream id=concept-cancel-readablestream>cancel</dfn> a
{{ReadableStream}} object <var>stream</var> with <var>reason</var>, return the result of calling
<a abstract-op>ReadableStreamCancel</a>(<var>stream</var>, <var>reason</var>).

<p class="note no-backref">Because the reader grants exclusive access, the actual mechanism of how
to read cannot be observed. Implementations could use more direct mechanism if convenient.

<p>To <dfn export for=ReadableStream id=concept-tee-readablestream>tee</dfn> a {{ReadableStream}}
object <var>stream</var>, run these steps:

<ol>
 <li><p>Return the result of calling <a abstract-op>ReadableStreamTee</a>(<var>stream</var>, true).
</ol>

<p>An <dfn export for=ReadableStream id=concept-empty-readablestream>empty</dfn> {{ReadableStream}}
object is the result of <a lt="construct a fixed ReadableStream object">constructing</a> a fixed
{{ReadableStream}} object with an empty list.

<p class="note no-backref">Constructing an <a>empty</a> {{ReadableStream}} object will not throw an
exception.

<p>A {{ReadableStream}} object <var>stream</var> is said to be
<dfn export for=ReadableStream id=concept-readablestream-readable>readable</dfn> if
<var>stream</var>.\[[state]] is "readable".

<p>A {{ReadableStream}} object <var>stream</var> is said to be
<dfn export for=ReadableStream id=concept-readablestream-closed>closed</dfn> if
<var>stream</var>.\[[state]] is "closed".

<p>A {{ReadableStream}} object <var>stream</var> is said to be
<dfn export for=ReadableStream id=concept-readablestream-errored>errored</dfn> if
<var>stream</var>.\[[state]] is "errored".

<p>A {{ReadableStream}} object <var>stream</var> is said to be
<dfn export for=ReadableStream id=concept-readablestream-locked>locked</dfn> if the
result of calling <a abstract-op>IsReadableStreamLocked</a>(<var>stream</var>) is
true.

<p>A {{ReadableStream}} object <var>stream</var> is said to
<dfn export for=ReadableStream id=concept-readablestream-need-more-data>need more data</dfn>
if the following conditions hold:

<ul>
 <li><p><var>stream</var> is <a for=ReadableStream>readable</a>.

 <li><p>The result of calling
 <a abstract-op>ReadableStreamDefaultControllerGetDesiredSize</a>(<var>stream</var>.\[[readableStreamController]]).
 is positive.
</ul>

<p>A {{ReadableStream}} object <var>stream</var> is said to be
<dfn export for=ReadableStream id=concept-readablestream-disturbed>disturbed</dfn>
if the result of calling
<a abstract-op>IsReadableStreamDisturbed</a>(<var>stream</var>) is true.



<h2 id=http-extensions>HTTP extensions</h2>

<h3 id=origin-header>`<code>Origin</code>` header</h3>

<p>The `<dfn export http-header id=http-origin><code>Origin</code></dfn>`
request <a for=/>header</a> indicates where a
<a for=/>fetch</a> originates from.

<p class="note no-backref">The `<a http-header><code>Origin</code></a>` header is a version of the
`<code>Referer</code>` [sic] header that does not reveal a <a for=url>path</a>. It is used for all
<a lt="HTTP fetch">HTTP fetches</a> whose <a for=/>request</a>'s
<a for=request>response tainting</a> is "<code>cors</code>", as well as those where
<a for=/>request</a>'s <a for=request>method</a> is neither `<code>GET</code>` nor
`<code>HEAD</code>`. Due to compatibility constraints it is not included in all
<a lt=fetch for=/>fetches</a>.
<!-- Ian Hickson told me Adam Barth researched that -->

<p>Its <a for=header>value</a> <a>ABNF</a>:

<pre><code class=lang-abnf>
Origin                           = origin-or-null

origin-or-null                   = origin / %s"null" ; case-sensitive
origin                           = <a for=url>scheme</a> "://" <a for=url>host</a> [ ":" <a for=url>port</a> ]
</code></pre>

<p class="note no-backref">This supplants the `<code>Origin</code>`
<a for=/>header</a>.
[[ORIGIN]]

<hr>

<p>To <dfn id=append-a-request-origin-header>append a request `<code>Origin</code>` header</dfn>,
given a <a for=/>request</a> <var>request</var>, run these steps:

<ol>
 <li><p>Let <var>serializedOrigin</var> be the result of <a>byte-serializing a request origin</a>
 with <var>request</var>.

 <li><p>If <var>request</var>'s <a for=request>response tainting</a> is "<code>cors</code>" or
 <var>request</var>'s <a for=request>mode</a> is "<code>websocket</code>", then
 <a for="header list">append</a> `<code>Origin</code>`/<var>serializedOrigin</var> to
 <var>request</var>'s <a for=request>header list</a>.

 <li>
  <p>Otherwise, if <var>request</var>'s <a for=request>method</a> is neither `<code>GET</code>` nor
  `<code>HEAD</code>`, then:

  <ol>
   <li>
    <p>Switch on <var>request</var>'s <a for=request>referrer policy</a>:

    <dl class=switch>
     <dt>"<code>no-referrer</code>"
     <dd><p>Set <var>serializedOrigin</var> to `<code>null</code>`.

     <dt>"<code>no-referrer-when-downgrade</code>"
     <dt>"<code>strict-origin</code>"
     <dt>"<code>strict-origin-when-cross-origin</code>"
     <dd><p>If <var>request</var>'s <a for=request>origin</a> is a <a>tuple origin</a>, its
     <var>scheme</var> is "<code>https</code>", and <var>request</var>'s
     <a for=request>current URL</a>'s <var>scheme</var> is not "<code>https</code>", then set
     <var>serializedOrigin</var> to `<code>null</code>`.

     <dt>"<code>same-origin</code>"
     <dd><p>If <var>request</var>'s <a for=request>origin</a> is not <a>same origin</a> with
     <var>request</var>'s <a for=request>current URL</a>'s <a for=url>origin</a>, then set
     <var>serializedOrigin</var> to `<code>null</code>`.

     <dt>Otherwise
     <dd>Do nothing.
    </dl>

   <li><p><a for="header list">Append</a> `<code>Origin</code>`/<var>serializedOrigin</var> to
   <var>request</var>'s <a for=request>header list</a>.
  </ol>
</ol>

<p class=note>A <a for=/>request</a>'s <a for=request>referrer policy</a> is taken into account for
all fetches where the fetcher did not explicitly opt into sharing their <a for=/>origin</a> with the
server, e.g., via using the <a>CORS protocol</a>.


<h3 id=http-cors-protocol>CORS protocol</h3>

<p>To allow sharing responses cross-origin and allow for more versatile
<a lt=fetch for=/>fetches</a> than possible with HTML's
<{form}> element, the <dfn export>CORS protocol</dfn> exists. It
is layered on top of HTTP and allows responses to declare they can be shared with other
<a for=/>origins</a>.

<p class=note>It needs to be an opt-in mechanism to prevent leaking data from responses behind a
firewall (intranets). Additionally, for <a for=/>requests</a> including
<a for=/>credentials</a> it needs to be opt-in to prevent leaking potentially-sensitive data.

<p>This section explains the <a>CORS protocol</a> as it pertains to server developers.
Requirements for user agents are part of the <a for=/>fetch</a> algorithm,
except for the <a href=#http-new-header-syntax>new HTTP header syntax</a>.


<h4 id=general>General</h4>

<p>The <a>CORS protocol</a> consists of a set of headers that indicates whether a response can
be shared cross-origin.

<p>For <a for=/>requests</a> that are more involved than what is possible with HTML's <{form}>
element, a <a>CORS-preflight request</a> is performed, to ensure <a for=/>request</a>'s
<a for=request>current URL</a> supports the <a>CORS protocol</a>.


<h4 id=http-requests>HTTP requests</h4>

<p>A <dfn export>CORS request</dfn> is an HTTP request that includes an
`<a http-header><code>Origin</code></a>` header. It cannot be reliably identified as participating in
the <a>CORS protocol</a> as the `<a http-header><code>Origin</code></a>` header is also included for
all <a for=/>requests</a> whose <a for=request>method</a> is neither `<code>GET</code>` nor
`<code>HEAD</code>`.

<p>A <dfn id=cors-preflight-request export>CORS-preflight request</dfn> is a <a>CORS request</a> that checks to see
if the <a>CORS protocol</a> is understood. It uses `<code>OPTIONS</code>` as
<a for=/>method</a> and includes these
<a for=/>headers</a>:

<dl>
 <dt>`<dfn export http-header id=http-access-control-request-method><code>Access-Control-Request-Method</code></dfn>`
 <dd><p>Indicates which <a for=/>method</a> a future
 <a>CORS request</a> to the same resource might use.

 <dt>`<dfn export http-header id=http-access-control-request-headers><code>Access-Control-Request-Headers</code></dfn>`
 <dd><p>Indicates which <a for=/>headers</a> a future
 <a>CORS request</a> to the same resource might use.
</dl>


<h4 id=http-responses>HTTP responses</h4>

<p>An HTTP response to a <a>CORS request</a> can include the following
<a for=/>headers</a>:

<dl>
 <dt>`<dfn export http-header id=http-access-control-allow-origin><code>Access-Control-Allow-Origin</code></dfn>`
 <dd><p>Indicates whether the response can be shared, via returning the literal
 <a for=header>value</a> of the
 `<a http-header><code>Origin</code></a>` request <a for=/>header</a>
 (which can be `<code>null</code>`) or `<code>*</code>` in a response.

 <dt>`<dfn export http-header id=http-access-control-allow-credentials><code>Access-Control-Allow-Credentials</code></dfn>`
 <dd>
  <p>Indicates whether the response can be shared when <a for=/>request</a>'s
  <a for=request>credentials mode</a> is
  "<code>include</code>".

  <p class=note>For a <a>CORS-preflight request</a>,
  <a for=/>request</a>'s
  <a for=request>credentials mode</a> is always
  "<code>omit</code>", but for any subsequent
  <a>CORS requests</a> it might not be. Support therefore needs
  to be indicated as part of the HTTP response to the <a>CORS-preflight request</a>
  as well.
</dl>

<p>An HTTP response to a <a>CORS-preflight request</a> can include the following
<a for=/>headers</a>:

<dl>
 <dt>`<dfn export http-header id=http-access-control-allow-methods><code>Access-Control-Allow-Methods</code></dfn>`
 <dd>
  <p>Indicates which <a for=/>methods</a> are supported by the <a for=/>response</a>'s
  <a for=response>URL</a> for the purposes of the <a>CORS protocol</a>.

  <p class=note>The `<code>Allow</code>` <a for=/>header</a> is
  not relevant for the purposes of the <a>CORS protocol</a>.

 <dt>`<dfn export http-header id=http-access-control-allow-headers><code>Access-Control-Allow-Headers</code></dfn>`
 <dd><p>Indicates which <a for=/>headers</a> are supported by the <a for=/>response</a>'s
 <a for=response>URL</a> for the purposes of the <a>CORS protocol</a>.

 <dt>`<dfn export http-header id=http-access-control-max-age><code>Access-Control-Max-Age</code></dfn>`
 <dd><p>Indicates how long the information provided by the
 `<a http-header><code>Access-Control-Allow-Methods</code></a>` and
 `<a http-header><code>Access-Control-Allow-Headers</code></a>` <a for=/>headers</a> can be cached.
</dl>

<p>An HTTP response to a <a>CORS request</a> that is not a
<a>CORS-preflight request</a> can also include the following
<a for=/>header</a>:

<dl>
 <dt>`<dfn export http-header id=http-access-control-expose-headers><code>Access-Control-Expose-Headers</code></dfn>`
 <dd><p>Indicates which <a for=/>headers</a> can be exposed as part
 of the response by listing their <a lt=name for=header>names</a>.
</dl>

<hr>

<p>In case a server does not wish to participate in the <a>CORS protocol</a>, its HTTP response to
the <a lt="CORS request">CORS</a> or <a>CORS-preflight request</a> must not include any of the above
<a for=/>headers</a>. The server is encouraged to use the <code>403</code> <a for=/>status</a> in
such HTTP responses.


<h4 id=http-new-header-syntax>HTTP new-header syntax</h4>

<p><a>ABNF</a> for the <a lt=value for=header>values</a> of the
<a for=/>headers</a> used by the <a>CORS protocol</a>:

<pre><code class=lang-abnf>
Access-Control-Request-Method    = <a spec=http>method</a>
Access-Control-Request-Headers   = 1#<a spec=http>field-name</a>

wildcard                         = "*"
Access-Control-Allow-Origin      = origin-or-null / wildcard
Access-Control-Allow-Credentials = %s"true" ; case-sensitive
Access-Control-Expose-Headers    = #<a spec=http>field-name</a>
Access-Control-Max-Age           = <a spec=http-caching>delta-seconds</a>
Access-Control-Allow-Methods     = #<a spec=http>method</a>
Access-Control-Allow-Headers     = #<a spec=http>field-name</a>
</code></pre>

<p class=note>For `<code>Access-Control-Expose-Headers</code>`,
`<code>Access-Control-Allow-Methods</code>`, and `<code>Access-Control-Allow-Headers</code>`
response <a for=/>headers</a> the <a for=header>value</a> `<code>*</code>` counts as a wildcard for
<a for=/>requests</a> without <a for=/>credentials</a>. For such <a for=/>requests</a> there is no
way to solely match a <a for=/>header</a> <a for=header>name</a> or <a for=/>method</a> that is
`<code>*</code>`.


<h4 id=cors-protocol-and-credentials>CORS protocol and credentials</h4>

<!-- non-normative -->

<p>When <a for=/>request</a>'s
<a for=request>credentials mode</a> is "<code>include</code>" it
has an impact on the functioning of the <a>CORS protocol</a> other than including
<a for=/>credentials</a> in the <a for=/>fetch</a>.

<div id=example-xhr-credentials class=example>
 <p>In the old days, {{XMLHttpRequest}} could be used to set
 <a for=/>request</a>'s
 <a for=request>credentials mode</a> to "<code>include</code>":

 <pre><code class=lang-javascript>
var client = new XMLHttpRequest()
client.open("GET", "./")
client.withCredentials = true
/* … */
</code></pre>

 <p>Nowadays, <code>fetch("./", { credentials:"include" }).then(/* … */)</code>
 suffices.
</div>

<p>A <a for=/>request</a>'s
<a for=request>credentials mode</a> is not necessarily observable
on the server; only when <a for=/>credentials</a> exist for a
<a for=/>request</a> can it be observed by virtue of the
<a for=/>credentials</a> being included. Note that even so, a <a>CORS-preflight request</a>
never includes <a for=/>credentials</a>.

<p>The server developer therefore needs to decide whether or not responses "tainted" with
<a for=/>credentials</a> can be shared. And also needs to decide if
<a for=/>requests</a> necessitating a <a>CORS-preflight request</a> can
include <a for=/>credentials</a>. Generally speaking, both sharing responses and allowing requests
with <a for=/>credentials</a> is rather unsafe, and extreme care has to be taken to avoid the
<a href=https://en.wikipedia.org/wiki/Confused_deputy_problem>confused deputy problem</a>.
<!-- Turn into a reference? Meh. -->

<p>To share responses with <a for=/>credentials</a>, the
`<a http-header><code>Access-Control-Allow-Origin</code></a>` and
`<a http-header><code>Access-Control-Allow-Credentials</code></a>` <a for=/>headers</a> are
important. The following table serves to illustrate the various legal and illegal combinations for a
request to <code>https://rabbit.invalid/</code>:

<table>
 <tbody><tr>
  <th>Request's credentials mode
  <th>`<a http-header><code>Access-Control-Allow-Origin</code></a>`
  <th>`<a http-header><code>Access-Control-Allow-Credentials</code></a>`
  <th>Shared?
  <th>Notes
 <tr>
  <td>"<code>omit</code>"
  <td>`<code>*</code>`
  <td>Omitted
  <td>✅
  <td>—
 <tr>
  <td>"<code>omit</code>"
  <td>`<code>*</code>`
  <td>`<code>true</code>`
  <td>✅
  <td>If credentials mode is not "<code>include</code>", then
  `<a http-header><code>Access-Control-Allow-Credentials</code></a>` is ignored.
 <tr>
  <td>"<code>omit</code>"
  <td>`<code>https://rabbit.invalid/`</code>
  <td>Omitted
  <td>❌
  <td>A serialized origin has no trailing slash.
 <tr>
  <td>"<code>omit</code>"
  <td>`<code>https://rabbit.invalid`</code>
  <td>Omitted
  <td>✅
  <td>—
 <tr>
  <td>"<code>include</code>"
  <td>`<code>*</code>`
  <td>`<code>true</code>`
  <td>❌
  <td>If credentials mode is "<code>include</code>", then
  `<a http-header><code>Access-Control-Allow-Origin</code></a>` cannot be
  `<code>*</code>`.
 <tr>
  <td>"<code>include</code>"
  <td>`<code>https://rabbit.invalid`</code>
  <td>`<code>true</code>`
  <td>✅
  <td>—
 <tr>
  <td>"<code>include</code>"
  <td>`<code>https://rabbit.invalid`</code>
  <td>`<code>True</code>`
  <td>❌
  <td>`<code>true</code>` is (byte) case-sensitive.
</table>

<p>Similarly, `<a http-header><code>Access-Control-Expose-Headers</code></a>`,
`<a http-header><code>Access-Control-Allow-Methods</code></a>`, and
`<a http-header><code>Access-Control-Allow-Headers</code></a>` response headers can only use
`<code>*</code>` as value when <a for=/>request</a>'s <a for=request>credentials mode</a> is not
"<code>include</code>".


<h4 id=cors-protocol-examples>Examples</h4>

<div id=example-simple-cors class=example>
 <p>A script at <code>https://foo.invalid/</code> wants to fetch some data from
 <code>https://bar.invalid/</code>. (Neither <a for=/>credentials</a> nor response header access is
 important.)

 <pre id=unicorn><code class=lang-javascript>
var url = "https://bar.invalid/api?key=730d67a37d7f3d802e96396d00280768773813fbe726d116944d814422fc1a45&amp;data=about:unicorn";
fetch(url).then(success, failure)
</code></pre>

 <p>This will use the <a>CORS protocol</a>, though this is entirely transparent to the
 developer from <code>foo.invalid</code>. As part of the <a>CORS protocol</a>, the user agent
 will include the `<a http-header><code>Origin</code></a>` header in the request:

 <pre><code class=lang-http>
Origin: https://foo.invalid
</code></pre>

 <p>Upon receiving a response from <code>bar.invalid</code>, the user agent will verify the
 `<a http-header><code>Access-Control-Allow-Origin</code></a>` response header. If its value is
 either `<code>https://foo.invalid</code>` or `<code>*</code>`, the user agent will invoke the
 <code>success</code> callback. If it has any other value, or is missing, the user agent will invoke
 the <code>failure</code> callback.
</div>

<div id=example-cors-with-response-header class=example>
 <p>The developer of <code>foo.invalid</code> is back, and now wants to fetch some data from
 <code>bar.invalid</code> while also accessing a response header.

 <pre><code class=lang-javascript>
fetch(url).then(response => {
  var hsts = response.headers.get("strict-transport-security"),
      csp = response.headers.get("content-security-policy")
  log(hsts, csp)
})
</code></pre>

 <p><code>bar.invalid</code> provides a correct
 `<a http-header><code>Access-Control-Allow-Origin</code></a>` response header per the earlier
 example. The values of <code>hsts</code> and <code>csp</code> will depend on the
 `<a http-header><code>Access-Control-Expose-Headers</code></a>` response header. For example, if
 the response included the following headers

 <pre><code class=lang-http>
Content-Security-Policy: default-src 'self'
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
Access-Control-Expose-Headers: Content-Security-Policy
</code></pre>

 <p>then <code>hsts</code> would be null and <code>csp</code> would be
 "<code>default-src 'self'</code>", even though the response did include both headers. This is
 because <code>bar.invalid</code> needs to explicitly share each header by listing their names in
 the `<a http-header><code>Access-Control-Expose-Headers</code></a>` response header.

 <p>Alternatively, if <code>bar.invalid</code> wanted to share all its response headers, for
 requests that do not include <a for=/>credentials</a>, it could use `<code>*</code>` as value for
 the `<a http-header><code>Access-Control-Expose-Headers</code></a>` response header. If the request
 would have included <a for=/>credentials</a>, the response header names would have to be listed
 explicitly and `<code>*</code>` could not be used.
</div>

<div id=example-cors-with-credentials class=example>
 <p>The developer of <code>foo.invalid</code> returns, now fetching some data from
 <code>bar.invalid</code> while including <a for=/>credentials</a>. This time around the
 <a>CORS protocol</a> is no longer transparent to the developer as <a for=/>credentials</a>
 require an explicit opt-in:

 <pre><code class=lang-javascript>
fetch(url, { credentials:"include" }).then(success, failure)
</code></pre>

 <p>This also makes any `<code>Set-Cookie</code>` response headers <code>bar.invalid</code>
 includes fully functional (they are ignored otherwise).

 <p>The user agent will make sure to include any relevant <a for=/>credentials</a> in the request.
 It will also put stricter requirements on the response. Not only will <code>bar.invalid</code> need
 to list `<code>https://foo.invalid</code>` as value for the
 `<a http-header><code>Access-Control-Allow-Origin</code></a>` header (`<code>*</code>` is not
 allowed when <a for=/>credentials</a> are involved), the
 `<a http-header><code>Access-Control-Allow-Credentials</code></a>` header has to be present too:

 <pre><code class=lang-http>
Access-Control-Allow-Origin: https://foo.invalid
Access-Control-Allow-Credentials: true
</code></pre>

 <p>If the response does not include those two headers with those values, the <code>failure</code>
 callback will be invoked. However, any `<code>Set-Cookie</code>` response headers will be
 respected.
</div>


<h4 id=cors-protocol-exceptions>CORS protocol exceptions</h4>

<p>Specifications have allowed limited exceptions to the CORS safelist for non-safelisted
`<code>Content-Type</code>` header values. These exceptions are made for requests that can be
triggered by web content but whose headers and bodies can be only minimally controlled by the web
content. Therefore, servers should expect cross-origin web content to be allowed to trigger
non-preflighted requests with the following non-safelisted `<code>Content-Type</code>` header
values:

<ul class=brief>
 <li>`<code>application/csp-report</code>` [[CSP]]
 <li>`<code>application/expect-ct-report+json</code>` [[EXPECT-CT]]
 <li>`<code>application/xss-auditor-report</code>`
 <li>`<code>application/ocsp-request</code>` [[OCSP]]
</ul>

<p>Specifications should avoid introducing new exceptions and should only do so with careful
consideration for the security consequences. New exceptions can be proposed by
<a href=https://github.com/whatwg/fetch/issues/new>filing an issue</a>.


<h3 id=content-type-header>`<code>Content-Type</code>` header</h3>

<p>The `<code>Content-Type</code>` header is largely defined in HTTP. Its processing model is
defined here as the ABNF defined in HTTP is not compatible with web content. [[HTTP]]

<p>To
<dfn export for="header list" lt="extract a MIME type|extracting a MIME type" id=concept-header-extract-mime-type>extract a MIME type</dfn>
from a <a for=/>header list</a> <var>headers</var>, run these steps:

<ol>
 <li><p>Let <var>charset</var> be null.

 <li><p>Let <var>essence</var> be null.

 <li><p>Let <var>mimeType</var> be null.

 <li><p>Let <var>values</var> be the result of
 <a for="header list">getting, decoding, and splitting</a> `<code>Content-Type</code>` from
 <var>headers</var>.

 <li><p>If <var>values</var> is null, then return failure.

 <li>
  <p><a for=list>For each</a> <var>value</var> of <var>values</var>:

  <ol>
   <li><p>Let <var>temporaryMimeType</var> be the result of <a lt="parse a MIME type">parsing</a>
   <var>value</var>.

   <li><p>If <var>temporaryMimeType</var> is failure or its <a for="MIME type">essence</a> is
   "<code>*/*</code>", then <a for=iteration>continue</a>.

   <li><p>Set <var>mimeType</var> to <var>temporaryMimeType</var>.

   <li>
    <p>If <var>mimeType</var>'s <a for="MIME type">essence</a> is not <var>essence</var>, then:

    <ol>
     <li><p>Set <var>charset</var> to null.

     <li><p>If <var>mimeType</var>'s <a for="MIME type">parameters</a>["<code>charset</code>"]
     <a for=map>exists</a>, then set <var>charset</var> to <var>mimeType</var>'s
     <a for="MIME type">parameters</a>["<code>charset</code>"].

     <li><p>Set <var>essence</var> to <var>mimeType</var>'s <a for="MIME type">essence</a>.
    </ol>

   <li><p>Otherwise, if <var>mimeType</var>'s
   <a for="MIME type">parameters</a>["<code>charset</code>"] does not <a for=map>exist</a>, and
   <var>charset</var> is non-null, set <var>mimeType</var>'s
   <a for="MIME type">parameters</a>["<code>charset</code>"] to <var>charset</var>.
  </ol>

 <li><p>If <var>mimeType</var> is null, then return failure.

 <li><p>Return <var>mimeType</var>.
</ol>

<p class=warning>When <a>extract a MIME type</a> returns failure or a <a for=/>MIME type</a> whose
<a for="MIME type">essence</a> is incorrect for a given format, treat this as a fatal error.
Existing web platform features have not always followed this pattern, which has been a major source
of security vulnerabilities in those features over the years. In contrast, a
<a for=/>MIME type</a>'s <a for="MIME type">parameters</a> can typically be safely ignored.

<div class=example id=example-extract-a-mime-type>
 <p>This is how <a>extract a MIME type</a> functions in practice:

 <table>
  <tr>
   <th>Headers (as on the network)
   <th>Output (<a lt="serialize a MIME type">serialized</a>)
  <tr>
   <td>
    <pre><code class=lang-http>
Content-Type: text/plain;charset=gbk, text/html
</code></pre>
   <td><code>text/html</code>
  <tr>
   <td>
    <pre><code class=lang-http>
Content-Type: text/html;charset=gbk;a=b, text/html;x=y
</code></pre>
   <td rowspan=2><code>text/html;x=y;charset=gbk</code>
  <tr>
   <td>
    <pre><code class=lang-http>
Content-Type: text/html;charset=gbk;a=b
Content-Type: text/html;x=y
</code></pre>
  <tr>
   <td>
    <pre><code class=lang-http>
Content-Type: text/html;charset=gbk
Content-Type: x/x
Content-Type: text/html;x=y
</code></pre>
   <td><code>text/html;x=y</code>
  <tr>
   <td>
    <pre><code class=lang-http>
Content-Type: text/html
Content-Type: cannot-parse
</code></pre>
   <td rowspan=3><code>text/html</code>
  <tr>
   <td>
    <pre><code class=lang-http>
Content-Type: text/html
Content-Type: */*
</code></pre>
  <tr>
   <td>
    <pre><code class=lang-http>
Content-Type: text/html
Content-Type:
</code></pre>
 </table>
</div>



<h3 id=x-content-type-options-header>`<code>X-Content-Type-Options</code>` header</h3>

<p>The
`<dfn export http-header id=http-x-content-type-options><code>X-Content-Type-Options</code></dfn>`
response <a for=/>header</a> can be used to require checking of a <a for=/>response</a>'s
`<code>Content-Type</code>` <a for=/>header</a> against the <a for=request>destination</a> of a
<a for=/>request</a>.

<p>To <dfn export>determine nosniff</dfn>, given a <a for=/>header list</a> <var>list</var>, run
these steps:

<ol>
 <li><p>Let <var>values</var> be the result of
 <a for="header list">getting, decoding, and splitting</a>
 `<a http-header><code>X-Content-Type-Options</code></a>` from <var>list</var>.

 <li><p>If <var>values</var> is null, then return false.

 <li><p>If <var>values</var>[0] is an <a>ASCII case-insensitive</a> match for
 "<code>nosniff</code>", then return true.

 <li><p>Return false.
</ol>

<p>Web developers and conformance checkers must use the following <a for=header>value</a>
<a>ABNF</a> for `<a http-header><code>X-Content-Type-Options</code></a>`:

<pre><code class=lang-abnf>
X-Content-Type-Options           = "nosniff" ; case-insensitive
</code></pre>


<h4 lt="should response to request be blocked due to nosniff" dfn id=should-response-to-request-be-blocked-due-to-nosniff?>Should
<var>response</var> to <var>request</var> be blocked due to nosniff?</h4>

<p>Run these steps:

<ol>
 <li><p>If <a>determine nosniff</a> with <var>response</var>'s <a for=response>header list</a> is
 false, then return <b>allowed</b>.

 <li><p>Let <var>mimeType</var> be the result of <a for="header list">extracting a MIME type</a>
 from <var>response</var>'s <a for=response>header list</a>.

 <li><p>Let <var>destination</var> be <var>request</var>'s <a for=request>destination</a>.

 <li><p>If <var>destination</var> is <a for=request/destination>script-like</a> and
 <var>mimeType</var> is failure or is not a <a>JavaScript MIME type</a>, then return <b>blocked</b>.

 <li><p>If <var>destination</var> is "<code>style</code>" and <var>mimeType</var> is failure or its
 <a for="MIME type">essence</a> is not "<code>text/css</code>", then return <b>blocked</b>.

 <li><p>Return <b>allowed</b>.
</ol>

<p class="note no-backref">Only <a for=/>request</a> <a for=request>destinations</a> that are
<a for=request/destination>script-like</a> or "<code>style</code>" are considered as any exploits
pertain to them. Also, considering "<code>image</code>" was not compatible with deployed content.


<h3 id=corb>CORB</h3>

<p class="note">Cross-origin read blocking, better known as CORB, is an algorithm which identifies
dubious cross-origin resource fetches (e.g., fetches that would fail anyway like attempts to render
JSON inside an <code>img</code> element) and blocks them before they reach a web page. CORB reduces
the risk of leaking sensitive data by keeping it further from cross-origin web pages.

<p>A <dfn>CORB-protected MIME type</dfn> is an <a>HTML MIME type</a>, a <a>JSON MIME type</a>, or an
<a>XML MIME type</a> excluding <code>image/svg+xml</code>.

<p class="note no-backref">Even without CORB, accessing the content of cross-origin resources with
<a>CORB-protected MIME types</a> is either managed by the <a>CORS protocol</a> (e.g., in case of
{{XMLHttpRequest}}), not observable (e.g., in case of pings or CSP reports which ignore the
response), or would result in an error (e.g., when failing to decode an HTML document embedded in an
<code>img</code> element as an image). This means that CORB can block
<a>CORB-protected MIME types</a> resources without being disruptive to web pages.

<p>To perform a <dfn noexport>CORB check</dfn>, given a <var>request</var> and <var>response</var>,
run these steps:</p>

<ol>
 <li>
  <p>If <var>request</var>'s <a for=request>initiator</a> is "<code>download</code>", then return
  <b>allowed</b>.

  <p class=XXX>If we recast downloading as navigation this step can be removed.

 <li><p>If <var>request</var>'s <a for=request>current URL</a>'s <a for=url>scheme</a> is not an
 <a>HTTP(S) scheme</a>, then return <b>allowed</b>.

 <li><p>Let <var>mimeType</var> be the result of <a for="header list">extracting a MIME type</a>
 from <var>response</var>'s <a for=response>header list</a>.

 <li><p>If <var>mimeType</var> is failure, then return <b>allowed</b>.

 <li><p>If <var>response</var>'s <a for=response>status</a> is <code>206</code> and
 <var>mimeType</var> is a <a>CORB-protected MIME type</a>, then return <b>blocked</b>.

 <li>
  <p>If <a>determine nosniff</a> with <var>response</var>'s <a for=response>header list</a> is true
  and <var>mimeType</var> is a <a>CORB-protected MIME type</a> or its <a for="MIME type">essence</a>
  is "<code>text/plain</code>", then return <b>blocked</b>.

  <p class="note no-backref">CORB only protects <code>text/plain</code> responses with a
  `<code>X-Content-Type-Options: nosniff</code>` header. Unfortunately, protecting such responses
  without that header when their <a for=response>status</a> is <code>206</code> would break too many
  existing video responses that have a <code>text/plain</code> <a for=/>MIME type</a>.

 <!-- TODO: MIME type confirmation sniffing -->
 <!-- TODO: JSON security prefix sniffing -->

 <li><p>Return <b>allowed</b>.
</ol>


<h3 id=cross-origin-resource-policy-header>`<code>Cross-Origin-Resource-Policy</code>` header</h3>

<p>The
`<dfn export http-header id=http-cross-origin-resource-policy><code>Cross-Origin-Resource-Policy</code></dfn>`
response <a for=/>header</a> can be used to require checking a <a for=/>request</a>'s
<a for=request>current URL</a>'s <a for=url>origin</a> against a <a for=/>request</a>'s
<a for=request>origin</a> when <a for=/>request</a>'s <a for=request>mode</a> is
"<code>no-cors</code>".

<p>Its <a for=header>value</a> <a>ABNF</a>:

<pre><code class=lang-abnf>
Cross-Origin-Resource-Policy     = %s"same-origin" / %s"same-site" ; case-sensitive
</code></pre>

<p>To perform a <dfn>cross-origin resource policy check</dfn>, given a <var>request</var> and
<var>response</var>, run these steps:</p>

<ol>
 <li><p>If <var>request</var>'s <a for=request>mode</a> is not "<code>no-cors</code>", then return
 <b>allowed</b>.

 <li>
  <p>If <var>request</var>'s <a for=request>origin</a> is <a>same origin</a> with
  <var>request</var>'s <a for=request>current URL</a>'s <a for=url>origin</a>, then return
  <b>allowed</b>.

  <p class="note no-backref">While redirects that carry  a
  `<a http-header><code>Cross-Origin-Resource-Policy</code></a>` header are checked, redirects
  without such a header resulting in <var>response</var> do not affect the outcome as the default is
  <b>allowed</b>.
  <!-- This changes with COEP's cross-origin value. -->

 <li>
  <p>Let <var>policy</var> be the result of <a for="header list">getting</a>
  `<a http-header><code>Cross-Origin-Resource-Policy</code></a>` from <var>response</var>'s
  <a for=response>header list</a>.

  <p class=note>This means that `<code>Cross-Origin-Resource-Policy: same-site, same-origin</code>`
  ends up as <b>allowed</b> below as it will never match anything. Two or more
  `<a http-header><code>Cross-Origin-Resource-Policy</code></a>` headers will have the same effect.

 <li><p>If <var>policy</var> is `<code>same-origin</code>`, then return <b>blocked</b>.

 <li>
  <p>If the following are true

  <ul class=brief>
   <li><var>request</var>'s <a for=request>origin</a> is <a>schemelessly same site</a> with
   <var>request</var>'s <a for=request>current URL</a>'s <a for=url>origin</a>
   <li><var>request</var>'s <a for=request>origin</a>'s <a for=url>scheme</a> is
   "<code>https</code>" or <var>response</var>'s <a for=response>HTTPS state</a> is
   "<code>none</code>"
  </ul>

  <p>then return <b>allowed</b>.

  <p class=note>This prevents HTTPS responses with
  `<code>Cross-Origin-Resource-Policy: same-site</code>` from being accessed without secure
  transport.

 <li><p>If <var>policy</var> is `<code>same-site</code>`, then return <b>blocked</b>.

 <li><p>Return <b>allowed</b>.
</ol>



<h2 id=fetching>Fetching</h2>

<div class="note no-backref">
 <p>The algorithm below defines <a lt=fetch for=/>fetching</a>. In broad
 strokes, it takes a <a for=/>request</a> and outputs a
 <a for=/>response</a>.

 <p>That is, it either returns a <a for=/>response</a> if
 <a for=/>request</a>'s <a>synchronous flag</a> is set, or it
 <a lt="queue a fetch task">queues tasks</a> annotated <a>process response</a>,
 <a>process response end-of-body</a>, and <a>process response done</a> for the
 <a for=/>response</a>.

 <p>To capture uploads, if <a for=/>request</a>'s
 <a>synchronous flag</a> is unset,
 <a>tasks</a> annotated
 <a>process request body</a> and <a>process request end-of-body</a> for the
 <a for=/>request</a> can be
 <a lt="queue a fetch task">queued</a>.
</div>

<p>To perform a <dfn export id=concept-fetch>fetch</dfn> using <var>request</var>, run
the steps below. An ongoing <a for=/>fetch</a> can be
<dfn export for=fetch id=concept-fetch-terminate>terminated</dfn> with flag <var>aborted</var>,
which is unset unless otherwise specified.

<p>The user agent may be asked to
<dfn export for=fetch id=concept-fetch-suspend>suspend</dfn> the ongoing fetch.
The user agent may either accept or ignore the suspension request. The suspended fetch can be
<dfn export for=fetch id=concept-fetch-resume>resumed</dfn>. The user agent should
ignore the suspension request if the ongoing fetch is updating the response in the HTTP cache for
the request.

<p class="note no-backref">The user agent does not update the entry in the HTTP cache for a
<a for=/>request</a> if request's cache mode is "no-store" or a
`<code>Cache-Control: no-store</code>` header appears in the response.
[[!HTTP-CACHING]]

<ol>
 <li>
  <p>Run these steps, but <a>abort when</a> the ongoing fetch is <a for=fetch>terminated</a>:

  <ol>
   <li><p>If <var>request</var>'s <a for=request>window</a> is
   "<code>client</code>", set <var>request</var>'s
   <a for=request>window</a> to <var>request</var>'s
   <a for=request>client</a>, if <var>request</var>'s
   <a for=request>client</a>'s
   <a for="environment settings object">global object</a> is a
   {{Window}} object, and to "<code>no-window</code>"
   otherwise.

   <li><p>If <var>request</var>'s <a for=request>origin</a> is
   "<code>client</code>", set <var>request</var>'s
   <a for=request>origin</a> to  <var>request</var>'s
   <a for=request>client</a>'s <a for="environment settings object">origin</a>.

   <li>
    <p>If <var>request</var>'s <a for=request>header list</a>
    <a for="header list">does not contain</a> `<code>Accept</code>`, then:

    <ol>
     <li><p>Let <var>value</var> be `<code>*/*</code>`.

     <li><p>If <var>request</var> is a <a>navigation request</a>, a user agent should set
     <var>value</var> to
     `<code>text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</code>`.

     <li>
      <p>Otherwise, a user agent should set <var>value</var> to the first matching statement, if
      any, switching on <var>request</var>'s <a for=request>destination</a>:
      <!-- https://github.com/whatwg/fetch/issues/43#issuecomment-97909717 -->

      <dl class=switch>
       <dt>"<code>image</code>"
       <dd>`<code>image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5</code>`

       <dt>"<code>style</code>"
       <dd>`<code>text/css,*/*;q=0.1</code>`
      </dl>

     <li><p><a for="header list">Append</a>
     `<code>Accept</code>`/<var>value</var> to <var>request</var>'s
     <a for=request>header list</a>.
    </ol>

   <li><p>If <var>request</var>'s <a for=request>header list</a>
   <a for="header list">does not contain</a> `<code>Accept-Language</code>`, user agents should
   <a for="header list">append</a>
   `<code>Accept-Language</code>`/an appropriate <a for=header>value</a>
   to <var>request</var>'s <a for=request>header list</a>.

   <li>
    <p>If <var>request</var>'s <a for=request>priority</a> is null, then use <var>request</var>'s
    <a for=request>initiator</a> and <a for=request>destination</a> appropriately in setting
    <var>request</var>'s <a for=request>priority</a> to a user-agent-defined object.

    <p class=note>The user-agent-defined object could encompass stream weight and dependency
    for HTTP/2, and equivalent information used to prioritize dispatch and processing of
    HTTP/1 fetches.

   <li>
    <p>If <var>request</var> is a <a>subresource request</a>, then:

    <ol>
     <li><p>Let <var>record</var> be a new
     <a for="fetch group">fetch record</a> consisting of
     <var>request</var> and this instance of the
     <a for=/>fetch</a> algorithm.

     <li><p>Append <var>record</var> to <var>request</var>'s
     <a for=request>client</a>'s
     <a for=fetch>fetch group</a> list of
     <a for="fetch group">fetch records</a>.
    </ol>
  </ol>

 <li>
  <p><a>If aborted</a>, then:

  <ol>
   <li><p>Let <var>aborted</var> be the termination's aborted flag.

   <li><p>If <var>aborted</var> is set, then return an <a>aborted network error</a>.

   <li><p>Return a <a>network error</a>.
  </ol>

 <li><p>Return the result of performing a <a for=main>main fetch</a>
 using <var>request</var>.
</ol>


<h3 id=main-fetch>Main fetch</h3>

<p>To perform a <dfn id=concept-main-fetch for=main>main fetch</dfn> using <var>request</var>,
optionally with a <i>recursive flag</i>, run these steps:

<p class=note>When <a for=main>main fetch</a> is invoked recursively
<i>recursive flag</i> is set.

<ol>
 <li><p>Let <var>response</var> be null.

 <li>
  <p>Run these steps, but <a>abort when</a> the ongoing fetch is <a for=fetch>terminated</a>:

  <ol>

   <li><p>If <var>request</var>'s <a>local-URLs-only flag</a> is set and <var>request</var>'s
   <a for=request>current URL</a> is not <a lt="is local">local</a>, then set <var>response</var> to
   a <a>network error</a>.

   <li><p>Execute <a href=https://w3c.github.io/webappsec-csp/#report-for-request>Report Content Security Policy violations for <var>request</var></a>.
    [[!CSP]]

   <li><p><a href=https://w3c.github.io/webappsec-upgrade-insecure-requests/#upgrade-request>Upgrade <var>request</var> to a potentially secure URL, if appropriate</a>.
   [[!UPGRADE]]

   <li><p>If
   <a lt="block bad port">should fetching <var>request</var> be blocked due to a bad port</a>,
   <a href=https://w3c.github.io/webappsec-mixed-content/#should-block-fetch>should fetching <var>request</var> be blocked as mixed content</a>,
   or
   <a href=https://w3c.github.io/webappsec-csp/#should-block-request>should fetching <var>request</var> be blocked by Content Security Policy</a>
   returns <b>blocked</b>, set <var>response</var> to a
   <a>network error</a>.
   [[!MIX]]
   [[!CSP]]

   <li><p>If <var>request</var>'s <a for=request>referrer policy</a> is the empty string and
   <var>request</var>'s <a for=request>client</a> is non-null, then set <var>request</var>'s
   <a for=request>referrer policy</a> to <var>request</var>'s <a for=request>client</a>'s
   <a for="environment settings object">referrer policy</a>.
   [[!REFERRER]]

   <li>
    <p>If <var>request</var>'s <a for=request>referrer policy</a>
    is the empty string, then set <var>request</var>'s
    <a for=request>referrer policy</a> to
    "<code>no-referrer-when-downgrade</code>".

    <p class="note no-backref">We use "<code>no-referrer-when-downgrade</code>" because it is the
    historical default.

   <li>
    <p>If <var>request</var>'s <a for=request>referrer</a>
    is not "<code>no-referrer</code>", set <var>request</var>'s
    <a for=request>referrer</a> to the result of invoking
    <a>determine <var>request</var>'s referrer</a>.
    [[!REFERRER]]

    <p class="note no-backref">As stated in <cite>Referrer Policy</cite>, user agents can
    provide the end user with options to override <var>request</var>'s
    <a for=request>referrer</a> to "<code>no-referrer</code>" or
    have it expose less sensitive information.

   <li>
    <p>If <var>request</var>'s <a for=request>current URL</a>'s <a for=url>scheme</a> is
    "<code>ftp</code>", <var>request</var>'s <a for=request>client</a>'s
    <a for=environment>creation URL</a>'s <a for=url>scheme</a> is not "<code>ftp</code>", and
    <var>request</var>'s <a for=request>reserved client</a> is either null or an
    <a for=/>environment</a> whose <a for=environment>target browsing context</a> is a
    <a>nested browsing context</a>, then set <var>response</var> to a <a>network error</a>.

   <li>
    <p>Set <var>request</var>'s <a for=request>current URL</a>'s <a for=url>scheme</a> to
    "<code>https</code>" if all of the following conditions are true:

    <ul class=brief>
     <li><var>request</var>'s <a for=request>current URL</a>'s <a for=url>scheme</a> is
     "<code>http</code>"
     <li><var>request</var>'s <a for=request>current URL</a>'s <a for=url>host</a> is a
     <a for=/>domain</a>
     <li>Matching <var>request</var>'s <a for=request>current URL</a>'s <a for=url>host</a> per
     <a href=https://tools.ietf.org/html/rfc6797#section-8.2>Known HSTS Host Domain Name Matching</a>
     results in either a superdomain match with an asserted <code>includeSubDomains</code> directive
     or a congruent match (with or without an asserted <code>includeSubDomains</code> directive).
     [[!HSTS]]
    </ul>
   <!-- Per Mike West HSTS happens "probably after" Referrer -->
  </ol>

  <li>
   <p><a>If aborted</a>, then:

   <ol>
    <li><p>Let <var>aborted</var> be the termination's aborted flag.

    <li><p>If <var>aborted</var> is set, then return an <a>aborted network error</a>.

    <li><p>Return a <a>network error</a>.
   </ol>

 <li><p>If <var>request</var>'s <a>synchronous flag</a> is unset and
 <i>recursive flag</i> is unset, run the remaining steps
 <a>in parallel</a>.

 <li>
  <p>If <var>response</var> is null, then set <var>response</var> to the result of running the steps
  corresponding to the first matching statement:

  <dl class=switch>
   <dt><var>request</var>'s <a for=request>current URL</a>'s <a for=url>origin</a> is
   <a>same origin</a> with <var>request</var>'s <a for=request>origin</a>, and <var>request</var>'s
   <a for=request>response tainting</a> is "<code>basic</code>"
   <dt><var>request</var>'s <a for=request>current URL</a>'s <a for=url>scheme</a> is
   "<code>data</code>"
   <dt><var>request</var>'s <a for=request>mode</a> is
   "<code>navigate</code>" or "<code>websocket</code>"

   <dd>
    <ol>
     <li><p>Set <var>request</var>'s
     <a for=request>response tainting</a> to "<code>basic</code>".

     <li><p>Return the result of performing a <a>scheme fetch</a>
     using <var>request</var>.
    </ol>

    <p class="note no-backref">HTML assigns any documents and workers created from <a for=/>URLs</a>
    whose <a for=url>scheme</a> is "<code>data</code>" a unique <a>opaque origin</a>. Service
    workers can only be created from <a for=/>URLs</a> whose <a for=url>scheme</a> is an
    <a>HTTP(S) scheme</a>.
    [[!HTML]] [[!SW]]

   <dt><var>request</var>'s <a for=request>mode</a> is
   "<code>same-origin</code>"

   <dd><p>Return a <a>network error</a>.

   <dt><var>request</var>'s <a for=request>mode</a> is
   "<code>no-cors</code>"
   <dd>
    <ol>
     <li><p>If <var>request</var>'s <a for=request>redirect mode</a> is not "<code>follow</code>",
     then return a <a>network error</a>.

     <li><p>Set <var>request</var>'s
     <a for=request>response tainting</a> to
     "<code>opaque</code>".

     <li><p>Let <var>noCorsResponse</var> be the result of performing a <a>scheme fetch</a> using
     <var>request</var>.
     <!-- file URLs end up here as they are not same-origin typically. -->

     <li><p>If <var>noCorsResponse</var> is a <a>filtered response</a> or the <a>CORB check</a> with
     <var>request</var> and <var>noCorsResponse</var> returns <b>allowed</b>, then return
     <var>noCorsResponse</var>.

     <li>
      <p>Return a new <a for=/>response</a> whose <a for=response>status</a> is
      <var>noCorsResponse</var>'s <a for=response>status</a>, <a for=response>HTTPS state</a> is
      <var>noCorsResponse</var>'s <a for=response>HTTPS state</a>, and <a for=response>CSP list</a>
      is <var>noCorsResponse</var>'s <a for=response>CSP list</a>.

      <p class="warning">This is only an effective defense against side channel attacks if
      <var>noCorsResponse</var> is kept isolated from the process that initiated the request.
    </ol>

   <dt><var>request</var>'s <a for=request>current URL</a>'s <a for=url>scheme</a> is not an
   <a>HTTP(S) scheme</a>

   <dd><p>Return a <a>network error</a>.

   <dt><var>request</var>'s <a>use-CORS-preflight flag</a> is set
   <dt><var>request</var>'s <a>unsafe-request flag</a> is set and either <var>request</var>'s
   <a for=request>method</a> is not a <a>CORS-safelisted method</a> or
   <a>CORS-unsafe request-header names</a> with <var>request</var>'s <a for=request>header list</a>
   <a for=list>is not empty</a>
   <dd>
    <ol>
     <li><p>Set <var>request</var>'s
     <a for=request>response tainting</a> to
     "<code>cors</code>".

     <li><p>Let <var>corsWithPreflightResponse</var> be the result of performing an
     <a>HTTP fetch</a> using <var>request</var> with the <i>CORS-preflight flag</i> set.

     <li><p>If <var>corsWithPreflightResponse</var> is a <a>network error</a>, then
     <a>clear cache entries</a> using <var>request</var>.

     <li><p>Return <var>corsWithPreflightResponse</var>.
    </ol>

   <dt>Otherwise
   <dd>
    <ol>
     <li><p>Set <var>request</var>'s
     <a for=request>response tainting</a> to
     "<code>cors</code>".

     <li><p>Return the result of performing an <a>HTTP fetch</a> using <var>request</var>.
    </ol>
  </dl>

 <li><p>If the <i>recursive flag</i> is set, return <var>response</var>.

 <li>
  <p>If <var>response</var> is not a <a>network error</a> and <var>response</var> is not a
  <a>filtered response</a>, then:

  <ol>
   <li>
    <p>If <var>request</var>'s <a for=request>response tainting</a> is "<code>cors</code>", then:

    <ol>
     <li><p>Let <var>headerNames</var> be the result of <a>extracting header list values</a> given
     `<a http-header><code>Access-Control-Expose-Headers</code></a>` and <var>response</var>'s
     <a for=response>header list</a>.

     <li><p>If <var>request</var>'s <a for=request>credentials mode</a> is not
     "<code>include</code>" and <var>headerNames</var> contains `<code>*</code>`, then set
     <var>response</var>'s <a for=response>CORS-exposed header-name list</a> to all unique
     <a for=/>header</a> <a lt=name for=header>names</a> in <var>response</var>'s
     <a for=response>header list</a>.

     <li>
      <p>Otherwise, if <var>headerNames</var> is not null or failure, then set <var>response</var>'s
      <a for=response>CORS-exposed header-name list</a> to <var>headerNames</var>.

      <p class="note">One of the <var>headerNames</var> can still be `<code>*</code>` at this point,
      but will only match a <a for=/>header</a> whose <a for=header>name</a> is `<code>*</code>`.
    </ol>

   <li>
    <p>Set <var>response</var> to the following
    <a>filtered response</a> with <var>response</var> as its
    <a for=internal>internal response</a>, depending on
    <var>request</var>'s <a for=request>response tainting</a>:

    <dl class="switch compact">
     <dt>"<code>basic</code>"
     <dd><a>basic filtered response</a>
     <dt>"<code>cors</code>"
     <dd><a>CORS filtered response</a>
     <dt>"<code>opaque</code>"
     <dd><a>opaque filtered response</a>
    </dl>
  </ol>

 <li><p>Let <var>internalResponse</var> be <var>response</var>, if <var>response</var> is a
 <a>network error</a>, and <var>response</var>'s
 <a for=internal>internal response</a> otherwise.

 <li>
  <p>If <var>internalResponse</var>'s <a for=response>URL list</a> <a for=list>is empty</a>, then
  set it to a <a for=list>clone</a> of <var>request</var>'s <a for=request>URL list</a>.

  <p class=note>A <a for=/>response</a>'s <a for=response>URL list</a> will typically be empty at
  this point, unless it came from a service worker, in which case it will only be empty if it was
  created through <a lt="Response()" constructor><code>new Response()</code></a>.
 <!-- If you are ever tempted to move this around, carefully consider responses from about URLs,
      blob URLs, service workers, HTTP cache, HTTP network, etc. -->

 <li><p>If <var>request</var>'s <a for=request>timing allow failed flag</a> is unset, then set
 <var>internalResponse</var>'s <a for=response>timing allow passed flag</a>.

 <li><p><a href=https://w3c.github.io/webappsec-csp/#set-response-csp-list>Set <var>internalResponse</var>'s CSP list</a>.
 [[!CSP]]

 <li>
  <p>If <var>response</var> is not a <a>network error</a> and any
  of the following algorithms returns <b>blocked</b>, then set <var>response</var> and
  <var>internalResponse</var> to a <a>network error</a>:

  <ul class=brief>
   <li><a href=https://w3c.github.io/webappsec-mixed-content/#should-block-response>should <var>internalResponse</var> to <var>request</var> be blocked as mixed content</a>
   [[!MIX]]
   <li><a href=https://w3c.github.io/webappsec-csp/#should-block-response>should <var>internalResponse</var> to <var>request</var> be blocked by Content Security Policy</a>
   [[!CSP]]
   <li><a lt="should response to request be blocked due to mime type">should <var>internalResponse</var> to <var>request</var> be blocked due to its MIME type</a>
   <li><a lt="should response to request be blocked due to nosniff">should <var>internalResponse</var> to <var>request</var> be blocked due to nosniff</a>
  </ul>

 <li>
  <p>If <var>response</var>'s <a for=response>type</a> is "<code>opaque</code>",
  <var>internalResponse</var>'s <a for=response>status</a> is <code>206</code>,
  <var>internalResponse</var>'s <a for=response>range-requested flag</a> is set, and
  <var>request</var>'s <a for=request>header list</a> does not <a for="header list">contain</a>
  `<code>Range</code>`, then set <var>response</var> and <var>internalResponse</var> to a
  <a>network error</a>.

  <div class=note>
   <p>Traditionally, APIs accept a ranged response even if a range was not requested. This prevents
   a partial response from an earlier ranged request being provided to an API that did not make a
   range request.

   <details>
    <summary>Further details</summary>

    <p>The above steps prevent the following attack:

    <p>A media element is used to request a range of a cross-origin HTML resource. Although this is
    invalid media, a reference to a clone of the response can be retained in a service worker. This
    can later be used as the response to a script element's fetch. If the partial response is valid
    JavaScript (even though the whole resource is not), executing it would leak private data.
   </details>
  </div>

 <li>
  <p>If <var>response</var> is not a <a>network error</a> and
  either <var>request</var>'s <a for=request>method</a> is
  `<code>HEAD</code>` or `<code>CONNECT</code>`, or <var>internalResponse</var>'s
  <a for=response>status</a> is a <a>null body status</a>,
  set <var>internalResponse</var>'s <a for=response>body</a> to
  null and disregard any enqueuing toward it (if any).

  <p class=note>This standardizes the error handling for servers that violate HTTP.

 <li>
  <p>If <var>response</var> is not a <a>network error</a> and <var>request</var>'s
  <a for=request>integrity metadata</a> is not the empty string, then:

  <ol>
   <li><p><a lt=wait for=body>Wait</a> for <var>response</var>'s
   <a for=response>body</a>.

   <li><p>If <var>response</var>'s <a for=response>body</a>'s <a for=body>stream</a> has not
   <a for=ReadableStream>errored</a>, and <var>response</var> does not
   <a href=https://w3c.github.io/webappsec-subresource-integrity/#does-response-match-metadatalist>match</a>
   <var>request</var>'s <a for=request>integrity metadata</a>, set <var>response</var> and
   <var>internalResponse</var> to a <a>network error</a>.
   [[!SRI]]
  </ol>

  <p class=note>This operates on <var>response</var> as this algorithm is not supposed to observe
  <var>internalResponse</var>. That would allow an attacker to use hashes as an oracle.

 <li>
  <p>If <var>request</var>'s <a>synchronous flag</a> is set,
  <a for=body>wait</a> for <var>internalResponse</var>'s
  <a for=response>body</a>, and then return <var>response</var>.

  <p class="note no-backref">This terminates <a for=/>fetch</a>.

 <li>
  <p>If <var>request</var>'s <a for=request>current URL</a>'s <a for=url>scheme</a> is an
  <a>HTTP(S) scheme</a>, then:

  <ol>
   <li><p>If <var>request</var>'s <a for=request>body</a> is
   <a for=body>done</a>, <a>queue a fetch-request-done task</a> for
   <var>request</var>.

   <li><p>Otherwise, <a>in parallel</a>,
   <a for=body>wait</a> for <var>request</var>'s
   <a for=request>body</a>, and then
   <a>queue a fetch-request-done task</a> for <var>request</var>.
  </ol>

 <li><p><a>Queue a fetch task</a> on <var>request</var> to
 <a>process response</a> for <var>response</var>.

 <li><p><a lt=wait for=body>Wait</a> for <var>internalResponse</var>'s
 <a for=response>body</a>.

 <li><p><a>Queue a fetch task</a> on <var>request</var> to
 <a>process response end-of-body</a> for <var>response</var>.

 <li><p>Set <var>request</var>'s <a>done flag</a>.

 <li><p><a>Queue a fetch task</a> on <var>request</var> to <a>process response done</a>
 for <var>response</var>.
</ol>

<!-- Prior to May 2017, this algorithm was named "basic fetch." -->
<h3 id=scheme-fetch oldids=basic-fetch>Scheme fetch</h3>

<p>To perform a <dfn id=concept-scheme-fetch oldids=concept-basic-fetch>scheme fetch</dfn> using
<var>request</var>, switch on <var>request</var>'s <a for=request>current URL</a>'s
<a for=url>scheme</a>, and run the associated steps:

<dl class=switch>
 <dt>"<code>about</code>"
 <dd>
  <p>If <var>request</var>'s <a for=request>current URL</a>'s <a>cannot-be-a-base-URL flag</a> is
  set and <a for=url>path</a> contains a single string "<code>blank</code>", then return a new
  <a for=/>response</a> whose <a for=response>status message</a> is `<code>OK</code>`,
  <a for=response>header list</a> consist of a single <a for=/>header</a> whose
  <a for=header>name</a> is `<code>Content-Type</code>` and <a for=header>value</a> is
  `<code>text/html;charset=utf-8</code>`, <a for=response>body</a> is the empty byte sequence, and
  <a for=response>HTTPS state</a> is <var>request</var>'s <a for=request>client</a>'s
  <a for="environment settings object">HTTPS state</a> if <var>request</var>'s
  <a for=request>client</a> is non-null.

  <p>Otherwise, return a <a>network error</a>.

  <p class="note no-backref"><a for=/>URLs</a> such as "<code>about:config</code>" are handled
  during <a lt=navigate>navigation</a> and result in a <a>network error</a> in the context of
  <a lt=fetch for=/>fetching</a>.

 <dt>"<code>blob</code>"
 <dd>
  <ol>
   <li>
    <p>Run these steps, but <a>abort when</a> the ongoing fetch is <a for=fetch>terminated</a>:

    <ol>
     <li><p>Let <var>blob</var> be <var>request</var>'s <a for=request>current URL</a>'s
     <a for=url>blob URL entry</a>'s <a for="blob URL entry">object</a>.

     <li>
      <p>If <var>request</var>'s <a for=request>method</a> is not `<code>GET</code>` or
      <var>blob</var> is not a {{Blob}} object, then return a <a>network error</a>. [[!FILEAPI]]

      <p class=note>The `<code>GET</code>` <a for=/>method</a> restriction serves no useful purpose
      other than being interoperable.

     <li><p>Let <var>response</var> be a new <a for=/>response</a> whose
     <a for=response>status message</a> is `<code>OK</code>`.

     <li><p><a for="header list">Append</a>
     `<code>Content-Length</code>`/<var>blob</var>'s
     {{Blob/size}} attribute value to
     <var>response</var>'s
     <a for=response>header list</a>.

     <li><p><a for="header list">Append</a>
     `<code>Content-Type</code>`/<var>blob</var>'s
     {{Blob/type}} attribute value to
     <var>response</var>'s
     <a for=response>header list</a>.

     <li><p>Set <var>response</var>'s
     <a for=response>HTTPS state</a> to <var>request</var>'s
     <a for=request>client</a>'s <a for="environment settings object">HTTPS state</a>
     if <var>request</var>'s <a for=request>client</a> is non-null.

     <li><p>Set <var>response</var>'s <a for=response>body</a> to
     the result of performing the <a spec=fileapi>read operation</a> on
     <var>blob</var>.

     <!-- This takes care of setting length, transmitted, and error flag as well -->

     <li><p>Return <var>response</var>.
    </ol>

   <li>
    <p><a>If aborted</a>, then:

    <ol>
     <li><p>Let <var>aborted</var> be the termination's aborted flag.

     <li><p>If <var>aborted</var> is set, then return an <a>aborted network error</a>.

     <li><p>Return a <a>network error</a>.
    </ol>
  </ol>

 <dt>"<code>data</code>"
 <dd>
  <ol>
   <li><p>Let <var>dataURLStruct</var> be the result of running the
   <a><code>data:</code> URL processor</a> on <var>request</var>'s <a for=request>current URL</a>.

   <li><p>If <var>dataURLStruct</var> is failure, then return a <a>network error</a>.

   <li><p>Return a <a for=/>response</a> whose <a for=response>status message</a> is
   `<code>OK</code>`, <a for=response>header list</a> consist of a single <a for=/>header</a> whose
   <a for=header>name</a> is `<code>Content-Type</code>` and <a for=header>value</a> is
   <var>dataURLStruct</var>'s <a for="data: URL struct">MIME type</a>,
   <a lt="serialize a MIME type to bytes">serialized</a>, <a for=response>body</a> is
   <var>dataURLStruct</var>'s <a for="data: URL struct">body</a>, and
   <a for=response>HTTPS state</a> is <var>request</var>'s <a for=request>client</a>'s
   <a for="environment settings object">HTTPS state</a> if <var>request</var>'s
   <a for=request>client</a> is non-null.
  </ol>

 <dt>"<code>file</code>"
 <dd>
  <p>For now, unfortunate as it is, <code>file</code> <a for=/>URLs</a> are left as an exercise for
  the reader.

  <p>When in doubt, return a <a>network error</a>.

 <dt>"<code>ftp</code>"
 <dd>
  <p>For now, unfortunate as it is, <code>ftp</code> <a for=/>URLs</a> are mostly left as an
  exercise for the reader.

  <ol>
   <li><p>Let <var>body</var> be the result of the user agent obtaining content from
   <var>request</var>'s <a for=request>current URL</a> from the network via FTP. [[!RFC959]]

   <li><p>Let </var>mime</var> be `<code>application/octet-stream</code>`.

   <li><p>If <var>body</var> is the result of the user agent generating a directory listing page for
   the result of FTP's LIST command, then set |mime| to `<code>text/ftp-dir</code>`.

   <li><p>Return a <a for=/>response</a> whose <a for="response">status message</a> is
   `<code>OK</code>`, <a for=response>header list</a> consists of a single <a for=/>header</a>
   whose <a for=header>name</a> is `<code>Content-Type</code>` and whose <a for=header>value</a> is
   <var>mime</var>, <a for=response>body</a> is <var>body</var>, and
   <a for=response>HTTPS state</a> is "<code>none</code>".
  </ol>

  <p>When in doubt, return a <a>network error</a>.

 <dt><a>HTTP(S) scheme</a>
 <dd>
  <p>Return the result of performing an <a>HTTP fetch</a>
  using <var>request</var>.

 <dt>Otherwise
 <dd><p>Return a <a>network error</a>.
</dl>


<h3 id=http-fetch>HTTP fetch</h3>

<p>To perform an <dfn id=concept-http-fetch export>HTTP fetch</dfn> using <var>request</var> with an
optional <i>CORS-preflight flag</i>, run these steps:

<p class="note no-backref">The <i>CORS-preflight flag</i> bookkeeping detail indicates a
<a>CORS-preflight request</a> is needed.

<ol>
 <li><p>Let <var>response</var> be null.

 <li><p>Let <var>actualResponse</var> be null.

 <li>
  <p>If <var>request</var>'s <a>service-workers mode</a> is "<code>all</code>", then:

  <ol>
   <li><p>Set <var>response</var> to the result of invoking <a for=/>handle fetch</a> for
   <var>request</var>. [[!HTML]] [[!SW]]

   <li>
    <p>If <var>response</var> is not null, then:

    <ol>
     <li><p><a for=request>Transmit body</a> for <var>request</var>.

     <li><p>Set <var>actualResponse</var> to <var>response</var>, if <var>response</var> is not a
     <a>filtered response</a>, and to <var>response</var>'s
     <a for=internal>internal response</a> otherwise.

     <li>
      <p>If one of the following is true

      <ul class=brief>
       <li><p><var>response</var>'s <a for=response>type</a> is "<code>error</code>"

       <li><p><var>request</var>'s <a for=request>mode</a> is "<code>same-origin</code>" and
       <var>response</var>'s <a for=response>type</a> is "<code>cors</code>"

       <li><p><var>request</var>'s <a for=request>mode</a> is not "<code>no-cors</code>" and
       <var>response</var>'s <a for=response>type</a> is "<code>opaque</code>"

       <li><var>request</var>'s <a for=request>redirect mode</a> is not "<code>manual</code>" and
       <var>response</var>'s <a for=response>type</a> is "<code>opaqueredirect</code>"

       <li><var>request</var>'s <a for=request>redirect mode</a> is not "<code>follow</code>" and
       <var>response</var>'s <a for=response>URL list</a> has more than one item.
      </ul>

      <p>then return a <a>network error</a>.
    </ol>
  </ol>

 <li>
  <p>If <var>response</var> is null, then:

  <ol>
   <li>
    <p>If the <i>CORS-preflight flag</i> is set and one of these conditions is true:

    <ul class=brief>
     <li><p>There is no <a>method cache entry match</a> for <var>request</var>'s
     <a for=request>method</a> using <var>request</var>, and either <var>request</var>'s
     <a for=request>method</a> is a not a <a>CORS-safelisted method</a> or <var>request</var>'s
     <a>use-CORS-preflight flag</a> is set.

     <li>There is at least one <a for=list>item</a> in the <a>CORS-unsafe request-header names</a>
     with <var>request</var>'s <a for=request>header list</a> for which there is no
     <a>header-name cache entry match</a> using <var>request</var>.
    </ul>

    <p>Then:

    <ol>
     <li><p>Let <var>preflightResponse</var> be the result of performing a
     <a>CORS-preflight fetch</a> using <var>request</var>.

     <li><p>If <var>preflightResponse</var> is a <a>network error</a>, then return
     <var>preflightResponse</var>.
    </ol>

    <p class="note no-backref">This step checks the
    <a>CORS-preflight cache</a> and if there is no suitable entry it
    performs a <a>CORS-preflight fetch</a> which, if successful, populates the cache. The
    purpose of the <a>CORS-preflight fetch</a> is to ensure the
    <a lt=fetch for=/>fetched</a> resource is familiar with the
    <a>CORS protocol</a>. The cache is there to minimize the number of
    <a lt="CORS-preflight fetch">CORS-preflight fetches</a>.

   <li>
    <p>If <var>request</var>'s <a for=request>redirect mode</a> is "<code>follow</code>", then set
    <var>request</var>'s <a>service-workers mode</a> to "<code>none</code>".

    <p class="note no-backref">Redirects coming from the network (as opposed to from a service
    worker) are not to be exposed to a service worker.

   <li><p>Set <var>response</var> and <var>actualResponse</var> to the result of performing an
   <a>HTTP-network-or-cache fetch</a> using <var>request</var>.

   <li>
    <p>If <var>request</var>'s <a for=request>response tainting</a> is "<code>cors</code>" and a
    <a>CORS check</a> for <var>request</var> and <var>response</var> returns failure, then return a
    <a>network error</a>.

    <p class="note no-backref">As the <a>CORS check</a> is not to be applied to
    <a for=/>responses</a> whose <a for=response>status</a> is <code>304</code> or <code>407</code>,
    or <a for=/>responses</a> from a service worker for that matter, it is applied here.

   <li><p>If the <a>TAO check</a> for <var>request</var> and <var>response</var> returns failure,
   then set <var>request</var>'s <a for=request>timing allow failed flag</a>.
  </ol>

 <li>
  <p>If <var>actualResponse</var>'s <a for=response>status</a> is a <a>redirect status</a>, then:

  <ol>
   <li>
    <p>If <var>actualResponse</var>'s <a for=response>status</a> is not <code>303</code>,
    <var>request</var>'s <a for=request>body</a> is not null, and the <a>connection</a> uses HTTP/2,
    then user agents may, and are even encouraged to, transmit an <code>RST_STREAM</code> frame.

    <p class=note><code>303</code> is excluded as certain communities ascribe special status to it.

   <li><p>Let <var>location</var> be the result of <a>extracting header list values</a> given
   `<code>Location</code>` and <var>actualResponse</var>'s <a for=response>header list</a>.

   <li><p>If <var>location</var> is a <a for=header>value</a>, then set <var>location</var> to the
   result of <a lt="url parser">parsing</a> <var>location</var> with <var>actualResponse</var>'s
   <a for=response>URL</a>.

   <li><p>Set <var>actualResponse</var>'s
   <a for=response>location URL</a> to <var>location</var>.

   <li>
    <p>Switch on <var>request</var>'s
    <a for=request>redirect mode</a>:

    <dl class=switch>
     <dt>"<code>error</code>"
     <dd><p>Set <var>response</var> to a <a>network error</a>.

     <dt>"<code>manual</code>"
     <dd><p>Set <var>response</var> to an
     <a>opaque-redirect filtered response</a>
     whose <a for=internal>internal response</a> is
     <var>actualResponse</var>.

     <dt>"<code>follow</code>"
     <dd><p>Set <var>response</var> to the result of performing <a>HTTP-redirect fetch</a> using
     <var>request</var> and <var>response</var>.
    </dl>
    <!-- not resetting actualResponse since it's no longer used anyway -->
  </ol>

 <li><p>Return <var>response</var>. <span class="note no-backref">Typically
 <var>actualResponse</var>'s <a for=response>body</a>'s
 <a for=body>stream</a> is still being enqueued to after returning.</span>
</ol>


<h3 id=http-redirect-fetch>HTTP-redirect fetch</h3>

<p class="note no-backref">This algorithm is used by HTML's navigate algorithm in addition to
<a>HTTP fetch</a> above. [[!HTML]]

<p>To perform an <dfn export id=concept-http-redirect-fetch>HTTP-redirect fetch</dfn> using
<var>request</var> and <var>response</var>, run these steps:

<ol>
 <li><p>Let <var>actualResponse</var> be <var>response</var>, if <var>response</var> is not a
 <a>filtered response</a>, and <var>response</var>'s
 <a for=internal>internal response</a> otherwise.

 <li><p>If <var>actualResponse</var>'s <a for=response>location URL</a>
 is null, then return <var>response</var>.

 <li><p>If <var>actualResponse</var>'s <a for=response>location URL</a>
 is failure, then return a <a>network error</a>.
 <!-- only Gecko does this; and even that is currently more complicated -->

 <li><p>If <var>actualResponse</var>'s
 <a for=response>location URL</a>'s
 <a for=url>scheme</a> is <em>not</em> an
 <a>HTTP(S) scheme</a>, then return a
 <a>network error</a>.

 <li><p>If <var>request</var>'s <a for=request>redirect count</a> is
 twenty, return a <a>network error</a>.

 <li><p>Increase <var>request</var>'s
 <a for=request>redirect count</a> by one.

 <li><p>If <var>request</var>'s <a for=request>mode</a> is "<code>cors</code>",
 <var>actualResponse</var>'s <a for=response>location URL</a>
 <a lt="include credential">includes credentials</a>, and <var>request</var>'s
 <a for=request>origin</a> is not <a>same origin</a> with <var>actualResponse</var>'s
 <a for=response>location URL</a>'s <a for=url>origin</a>, then return a <a>network error</a>.

 <li>
  <p>If <var>request</var>'s <a for=request>response tainting</a> is "<code>cors</code>" and
  <var>actualResponse</var>'s <a for=response>location URL</a>
  <a lt="include credential">includes credentials</a>, then return a <a>network error</a>.

  <p class=note>This catches a cross-origin resource redirecting to a same-origin URL.

 <li><p>If <var>actualResponse</var>'s <a for=response>status</a> is not <code>303</code>,
 <var>request</var>'s <a for=request>body</a> is non-null, and <var>request</var>'s
 <a for=request>body</a>'s <a for=body>source</a> is null, then return a <a>network error</a>.

 <li><p>If <var>actualResponse</var>'s <a for=response>location URL</a>'s <a for=url>origin</a> is
 not <a>same origin</a> with <var>request</var>'s <a for=request>current URL</a>'s
 <a for=url>origin</a> and <var>request</var>'s <a for=request>origin</a> is not <a>same origin</a>
 with <var>request</var>'s <a for=request>current URL</a>'s <a for=url>origin</a>, then set
 <var>request</var>'s <a for=request>tainted origin flag</a>.

 <li>
  <p>If one of the following is true

  <ul class=brief>
   <li><p><var>actualResponse</var>'s <a for=response>status</a> is <code>301</code> or
   <code>302</code> and <var>request</var>'s <a for=request>method</a> is `<code>POST</code>`
   <li><p><var>actualResponse</var>'s <a for=response>status</a> is <code>303</code> and
   <var>request</var>'s <a for=request>method</a> is not `<code>GET</code>` or `<code>HEAD</code>`
  </ul>

  <p>then:

  <ol>
   <li><p>Set <var>request</var>'s <a for=request>method</a> to `<code>GET</code>` and
   <var>request</var>'s <a for=request>body</a> to null.

   <li><p><a for="list">For each</a> <var>headerName</var> of <a>request-body-header name</a>,
   <a for="header list">delete</a> <var>headerName</var> from <var>request</var>'s
   <a for=request>header list</a>.
  </ol>

 <li>
  <p>If <var>request</var>'s <a for=request>body</a> is non-null, then set <var>request</var>'s
  <a for=request>body</a> to the first return value of <a for=BodyInit>safely extracting</a>
  <var>request</var>'s <a for=request>body</a>'s <a for=body>source</a>.

  <p class="note no-backref"><var>request</var>'s <a for=request>body</a>'s <a for=body>source</a>'s
  nullity has already been checked.

 <li><p>Append <var>actualResponse</var>'s <a for=response>location URL</a> to <var>request</var>'s
 <a for=request>URL list</a>.

 <li><p>Invoke <a>set <var>request</var>'s referrer policy on redirect</a> on <var>request</var> and
 <var>actualResponse</var>. [[!REFERRER]]

 <li>
  <p>Return the result of performing a <a for=main>main fetch</a> using <var>request</var> with
  <i>recursive flag</i> set if <var>request</var>'s <a for=request>redirect mode</a> is not
  "<code>manual</code>".

  <p class=note>It can only be "<code>manual</code>" when invoked directly from HTML's navigate
  algorithm.

  <p class="note no-backref">This has to invoke <a for=main>main fetch</a> to
  get <a for=request>response tainting</a> correct.
</ol>


<h3 id=http-network-or-cache-fetch>HTTP-network-or-cache fetch</h3>

<p>To perform an
<dfn id=concept-http-network-or-cache-fetch>HTTP-network-or-cache fetch</dfn> using
<var>request</var> with an optional <i>authentication-fetch flag</i>, run these steps:

<p class=note>The <i>authentication-fetch flag</i> is a bookkeeping detail.

<p class=note>Some implementations might support caching of partial content, as per <cite>HTTP
Range Requests</cite>. [[HTTP-RANGE]] However, this is not widely supported by browser caches.

<ol>
 <li><p>Let <var>httpRequest</var> be null.

 <li><p>Let <var>response</var> be null.

 <li><p>Let <var>storedResponse</var> be null.

 <li><p>Let the <var>revalidatingFlag</var> be unset.

 <li>
  <p>Run these steps, but <a>abort when</a> the ongoing fetch is <a for=fetch>terminated</a>:

  <ol>
   <li><p>If <var>request</var>'s <a for=request>window</a> is "<code>no-window</code>" and
   <var>request</var>'s <a for=request>redirect mode</a> is "<code>error</code>", then set
   <var>httpRequest</var> to <var>request</var>.

   <li>
    <p>Otherwise:

    <ol>
     <li><p>Set <var>httpRequest</var> to a copy of <var>request</var> except for its
     <a for=request>body</a>.

     <li><p>Let <var>body</var> be <var>request</var>'s <a for=request>body</a>.

     <li><p>Set <var>httpRequest</var>'s <a for=request>body</a> to <var>body</var>.

     <li><p>If <var>body</var> is non-null, then set <var>request</var>'s <a for=request>body</a> to
     a new <a for=/>body</a> whose <a for=body>stream</a> is null and whose <a for=body>source</a>
     is <var>body</var>'s <a for=body>source</a>.
    </ol>

    <p class="note no-backref"><var>request</var> is copied as <var>httpRequest</var> here as we
    need to be able to add headers to <var>httpRequest</var> and read its <a for=request>body</a>
    without affecting <var>request</var>. Namely, <var>request</var> can be reused with redirects,
    authentication, and proxy authentication. We copy rather than clone in order to reduce memory
    consumption. In case <var>request</var>'s <a for=request>body</a>'s <a for=body>source</a> is
    null, redirects and authentication will end up failing the fetch.

   <li>
    <p>Let <i>credentials flag</i> be set if one of

    <ul class=brief>
     <li><var>request</var>'s <a for=request>credentials mode</a> is
     "<code>include</code>"
     <li><var>request</var>'s  <a for=request>credentials mode</a> is
     "<code>same-origin</code>" and <var>request</var>'s
     <a for=request>response tainting</a> is "<code>basic</code>"
    </ul>

    <p>is true, and unset otherwise.

   <li><p>Let <var>contentLengthValue</var> be null.

   <li><p>If <var>httpRequest</var>'s <a for=request>body</a> is null and
   <var>httpRequest</var>'s <a for=request>method</a> is
   `<code>POST</code>` or `<code>PUT</code>`, then set <var>contentLengthValue</var> to
   `<code>0</code>`.
   <!-- https://chromium.googlesource.com/chromium/src/+/master/net/http/http_network_transaction.cc#982 -->

   <li><p>If <var>httpRequest</var>'s <a for=request>body</a> is non-null and <var>httpRequest</var>'s
   <a for=request>body</a>'s <a for=body>source</a> is non-null, then set
   <var>contentLengthValue</var> to <var>httpRequest</var>'s <a for=request>body</a>'s
   <a for=body>total bytes</a>, <a lt="serialize an integer">serialized</a> and
   <a>isomorphic encoded</a>.

   <li><p>If <var>contentLengthValue</var> is non-null,
   <a for="header list">append</a>
   `<code>Content-Length</code>`/<var>contentLengthValue</var> to
   <var>httpRequest</var>'s
   <a for=request>header list</a>.

   <li>
    <p>If <var>contentLengthValue</var> is non-null and <var>httpRequest</var>'s
    <a for=request>keepalive flag</a> is set, then:

    <ol>
     <li><p>Let <var>inflightKeepaliveBytes</var> be zero.

     <li><p>Let <var>group</var> be <var>httpRequest</var>'s <a for=request>client</a>'s
     <a>fetch group</a>.

     <li><p>Let <var>inflightRecords</var> be the set of <a for="fetch group">fetch records</a> in
     <var>group</var> whose <a for="fetch record">request</a> has its
     <a for=request>keepalive flag</a> set and <a>done flag</a> unset.

     <li>
      <p><a for=set>For each</a> <var>fetchRecord</var> in <var>inflightRecords</var>:

      <ol>
       <li><p>Let <var>inflightRequest</var> be <var>fetchRecord</var>'s
       <a for="fetch record">request</a>.

       <li><p>Increment <var>inflightKeepaliveBytes</var> by <var>inflightRequest</var>'s
       <a for=request>body</a>'s <a for=body>total bytes</a>.
      </ol>

     <li><p>If the sum of <var>contentLengthValue</var> and <var>inflightKeepaliveBytes</var> is
     greater than 64 kibibytes, then return a <a>network error</a>.
    </ol>

    <p class="note no-backref">The above limit ensures that requests that are allowed to outlive the
    <a>environment settings object</a> and contain a body, have a bounded size and are not allowed
    to stay alive indefinitely.

   <li><p>If <var>httpRequest</var>'s <a for=request>referrer</a> is a <a for=/>URL</a>, then
   <a for="header list">append</a> `<code>Referer</code>`/<var>httpRequest</var>'s
   <a for=request>referrer</a>, <a lt="url serializer">serialized</a> and <a>isomorphic encoded</a>,
   to <var>httpRequest</var>'s <a for=request>header list</a>.

   <li><p><a>Append a request `<code>Origin</code>` header</a> for <var>httpRequest</var>.

   <li><p>If <var>httpRequest</var>'s <a for=request>header list</a>
   <a for="header list">does not contain</a> `<code>User-Agent</code>`, then user agents should
   <a for="header list">append</a>
   `<code>User-Agent</code>`/<a>default `<code>User-Agent</code>` value</a>
   to <var>httpRequest</var>'s <a for=request>header list</a>.

   <li><p>If <var>httpRequest</var>'s <a for=request>cache mode</a> is "<code>default</code>" and
   <var>httpRequest</var>'s <a for=request>header list</a> <a for="header list">contains</a>
   `<code>If-Modified-Since</code>`,
   `<code>If-None-Match</code>`,
   `<code>If-Unmodified-Since</code>`,
   `<code>If-Match</code>`, or
   `<code>If-Range</code>`, then set <var>httpRequest</var>'s
   <a for=request>cache mode</a> to "<code>no-store</code>".

   <li><p>If <var>httpRequest</var>'s <a for=request>cache mode</a> is "<code>no-cache</code>",
   <var>httpRequest</var>'s <a for=request>prevent no-cache cache-control header modification flag</a>
   is unset, and <var>httpRequest</var>'s <a for=request>header list</a>
   <a for="header list">does not contain</a> `<code>Cache-Control</code>`, then
   <a for="header list">append</a> `<code>Cache-Control</code>`/`<code>max-age=0</code>` to
   <var>httpRequest</var>'s <a for=request>header list</a>.

   <li>
    <p>If <var>httpRequest</var>'s <a for=request>cache mode</a> is "<code>no-store</code>" or
    "<code>reload</code>", then:

    <ol>
     <li><p>If <var>httpRequest</var>'s <a for=request>header list</a>
     <a for="header list">does not contain</a> `<code>Pragma</code>`, then
     <a for="header list">append</a> `<code>Pragma</code>`/`<code>no-cache</code>` to
     <var>httpRequest</var>'s <a for=request>header list</a>.

     <li><p>If <var>httpRequest</var>'s <a for=request>header list</a>
     <a for="header list">does not contain</a> `<code>Cache-Control</code>`, then
     <a for="header list">append</a> `<code>Cache-Control</code>`/`<code>no-cache</code>` to
     <var>httpRequest</var>'s <a for=request>header list</a>.
     <!-- Technically this only applies to HTTP/1.1 and up -->
    </ol>

   <li>
    <p>If <var>httpRequest</var>'s <a for=request>header list</a> <a for="header list">contains</a>
    `<code>Range</code>`, then <a for="header list">append</a>
    `<code>Accept-Encoding</code>`/`<code>identity</code>` to <var>httpRequest</var>'s
    <a for=request>header list</a>.

    <div class="note no-backref">
     <p>This avoids a failure when <a lt="handle content codings">handling content codings</a> with
     a part of an encoded <a for=/>response</a>.

     <p>Additionally,
     <a href="https://jakearchibald.github.io/accept-encoding-range-test/">many servers</a>
     mistakenly ignore `<code>Range</code>` headers if a non-identity encoding is accepted.
    </div>

   <li>
    <p>Modify <var>httpRequest</var>'s <a for=request>header list</a> per HTTP. Do not
    <a for="header list">append</a> a given <a>header</a> if <var>httpRequest</var>'s
    <a for=request>header list</a> <a for="header list">contains</a> that <a>header</a>'s
    <a for=header>name</a>.

    <p class="note no-backref">It would be great if we could make this more normative
    somehow. At this point <a for=/>headers</a> such as
    `<code>Accept-Encoding</code>`,
    `<code>Connection</code>`,
    `<code>DNT</code>`, and
    `<code>Host</code>`,
    are to be <a for="header list">appended</a> if necessary.

    <p>`<code>Accept</code>`,
    `<code>Accept-Charset</code>`, and
    `<code>Accept-Language</code>` must not be included at this point.

    <p class="note no-backref">`<code>Accept</code>` and
    `<code>Accept-Language</code>` are already included (unless
    <a><code>fetch()</code></a> is used, which does not include the latter by
    default), and `<code>Accept-Charset</code>` is a waste of bytes. See
    <a>HTTP header layer division</a> for more details.

   <li>
    <p>If <i>credentials flag</i> is set, then:

    <ol>
     <li>
      <p>If the user agent is not configured to block cookies for <var>httpRequest</var> (see
      <a href=https://tools.ietf.org/html/rfc6265#section-7>section 7</a> of
      [[!COOKIES]]), then:

      <ol>
       <li><p>Let <var>cookies</var> be the result of running the "cookie-string" algorithm (see
       <a href=https://tools.ietf.org/html/rfc6265#section-5.4>section 5.4</a> of [[!COOKIES]]) with
       the user agent's cookie store and <var>httpRequest</var>'s <a for=request>current URL</a>.

       <li>If <var>cookies</var> is not the empty string, append
       `<code>Cookie</code>`/<var>cookies</var> to <var>httpRequest</var>'s
       <a for=request>header list</a>.
      </ol>

     <li>
      <p>If <var>httpRequest</var>'s <a for=request>header list</a>
      <a for="header list">does not contain</a> `<code>Authorization</code>`, then:

      <!-- https://wiki.whatwg.org/wiki/HTTP_Authentication -->
      <ol>
       <li><p>Let <var>authorizationValue</var> be null.

       <li><p>If there's an <a>authentication entry</a> for <var>httpRequest</var> and either
       <var>httpRequest</var>'s <a for=request>use-URL-credentials flag</a> is unset or
       <var>httpRequest</var>'s <a for=request>current URL</a> does not <a>include credentials</a>,
       then set <var>authorizationValue</var> to <a>authentication entry</a>.
       <!-- need to define the cache concept -->

       <li><p>Otherwise, if <var>httpRequest</var>'s <a for=request>current URL</a> does
       <a>include credentials</a> and <i>authentication-fetch flag</i> is set, set
       <var>authorizationValue</var> to <var>httpRequest</var>'s <a for=request>current URL</a>,
       <span class=XXX>converted to an `<code>Authorization</code>` value</span>.

       <li><p>If <var>authorizationValue</var> is non-null, then <a for="header list">append</a>
       `<code>Authorization</code>`/<var>authorizationValue</var> to <var>httpRequest</var>'s
       <a for=request>header list</a>.
      </ol>
    </ol>

   <li>
    <p>If there's a <a>proxy-authentication entry</a>, use it as appropriate.

    <p class="note no-backref">This intentionally does not depend on
    <var>httpRequest</var>'s
    <a for=request>credentials mode</a>.

   <li>
    <p>If <var>httpRequest</var>'s <a for=request>cache mode</a> is neither "<code>no-store</code>"
    nor "<code>reload</code>", then:

    <ol>
     <li>
      <p>Set <var>storedResponse</var> to the result of selecting a response from the HTTP cache,
      possibly needing validation, as per the
      "<a href=https://tools.ietf.org/html/rfc7234#section-4>Constructing Responses from Caches</a>"
      chapter of <cite>HTTP Caching</cite> [[!HTTP-CACHING]], if any.

      <p class=note>As mandated by HTTP, this still takes the `<code>Vary</code>`
      <a for=/>header</a> into account.

     <li>
      <p>If <var>storedResponse</var> is non-null, then:

      <!-- cache hit -->
      <ol>
       <li>
        <p>If <a for=request>cache mode</a> is "<code>default</code>", <var>storedResponse</var>
        is a <a>stale-while-revalidate response</a>, and <var>httpRequest</var>'s
        <a for=request>client</a> is non-null, then:

        <ol>
         <li><p>Set <var>response</var> to <var>storedResponse</var>.

         <li><p>Set <var>response</var>'s <a for=response>cache state</a> to "<code>local</code>".

         <li><p>Let <var>revalidateRequest</var> be a <a for=request>clone</a> of
         <var>request</var>.

         <li><p>Set <var>revalidateRequest</var>'s <a for=request>cache mode</a> set to
         "<code>no-cache</code>".

         <li><p>Set <var>revalidateRequest</var>'s
         <a for=request>prevent no-cache cache-control header modification flag</a>.

         <li><p>Set <var>revalidateRequest</var>'s <a for=request>service-workers mode</a> set to
         "<code>none</code>".

         <li>
          <p><a>In parallel</a>, perform <a for=main>main fetch</a> using
          <var>revalidateRequest</var>.

          <p class=note>This fetch is only meant to update the state of the HTTP cache and the
          response will be unused until another cache access. The stale response will be used as the
          response to current request. This fetch is issued in the context of a client so if it goes
          away the request will be terminated.
        </ol>

       <li>
        <p>Otherwise:

        <ol>
         <li><p>If <var>storedResponse</var> is a <a>stale response</a>, then set the
         <var>revalidatingFlag</var>.

         <li>
          <p>If the <var>revalidatingFlag</var> is set and <var>httpRequest</var>'s
          <a for=request>cache mode</a> is neither "<code>force-cache</code>" nor
          "<code>only-if-cached</code>", then:

          <ol>
           <li><p>If <var>storedResponse</var>'s <a for=response>header list</a>
           <a for="header list">contains</a> `<code>ETag</code>`, then
           <a for="header list">append</a> `<code>If-None-Match</code>` with its value to
           <var>httpRequest</var>'s <a for=request>header list</a>.

           <li><p>If <var>storedResponse</var>'s <a for=response>header list</a>
           <a for="header list">contains</a> `<code>Last-Modified</code>`, then
           <a for="header list">append</a> `<code>If-Modified-Since</code>` with its value to
           <var>httpRequest</var>'s <a for=request>header list</a>.
          </ol>

          <p class=note>See also the
          "<a href=https://tools.ietf.org/html/rfc7234#section-4.3.4>Sending a Validation Request</a>"
          chapter of <cite>HTTP Caching</cite> [[!HTTP-CACHING]].

         <li><p>Otherwise, set <var>response</var> to <var>storedResponse</var> and set
         <var>response</var>'s <a for=response>cache state</a> to "<code>local</code>".
        </ol>
      </ol>
    </ol>
  </ol>

 <li>
  <p><a>If aborted</a>, then:

  <ol>
   <li><p>Let <var>aborted</var> be the termination's aborted flag.

   <li><p>If <var>aborted</var> is set, then return an <a>aborted network error</a>.

   <li><p>Return a <a>network error</a>.
  </ol>

 <!-- If response is still null, we require a forwarded request. -->
 <li>
  <p>If <var>response</var> is null, then:

  <ol>
   <li><p>If <var>httpRequest</var>'s <a for=request>cache mode</a> is
   "<code>only-if-cached</code>", then return a <a>network error</a>.

   <li><p>Let <var>forwardResponse</var> be the result of making an <a>HTTP-network fetch</a> using
   <var>httpRequest</var> with <i>credentials flag</i> if set.

   <li><p>If <var>httpRequest</var>'s <a for=request>method</a> is
   <a href=https://tools.ietf.org/html/rfc7231#safe.methods>unsafe</a> and
   <var>forwardResponse</var>'s <a for=response>status</a> is in the range <code>200</code> to
   <code>399</code>, inclusive, invalidate appropriate stored responses in the HTTP cache, as per
   the "<a href=https://tools.ietf.org/html/rfc7234#section-4.4>Invalidation</a>" chapter of
   <cite>HTTP Caching</cite>, and set <var>storedResponse</var> to null. [[!HTTP-CACHING]]

   <li>
    <p>If the <var>revalidatingFlag</var> is set and <var>forwardResponse</var>'s
    <a for=response>status</a> is <code>304</code>, then:

    <ol>
     <li>
      <p>Update <var>storedResponse</var>'s <a for=response>header list</a> using
      <var>forwardResponse</var>'s <a for=response>header list</a>, as per the
      "<a href=https://tools.ietf.org/html/rfc7234#section-4.3.4>Freshening Stored Responses upon Validation</a>"
      chapter of <cite>HTTP Caching</cite>. [[!HTTP-CACHING]]

      <p class="note">This updates the stored response in cache as well.

     <li><p>Set <var>response</var> to <var>storedResponse</var>.

    </ol>

   <li>
    <p>If <var>response</var> is null, then:

    <ol>
     <li><p>Set <var>response</var> to <var>forwardResponse</var>.

     <li>
      <p>Store <var>httpRequest</var> and <var>forwardResponse</var> in the HTTP cache, as per the
      "<a href=https://tools.ietf.org/html/rfc7234#section-3>Storing Responses in Caches</a>"
      chapter of <cite>HTTP Caching</cite>. [[!HTTP-CACHING]]

      <p class=note>If <var>forwardResponse</var> is a <a>network error</a>, this effectively caches
      the network error, which is sometimes known as "negative caching".
    </ol>
  </ol>

 <li><p>If <var>httpRequest</var>'s <a for=request>header list</a> <a for="header list">contains</a>
 `<code>Range</code>`, then set <var>response</var>'s <a for=response>range-requested flag</a>.

 <li><p>If <var>httpRequest</var>'s <a for=request>response tainting</a> is not "<code>cors</code>"
 and the <a>cross-origin resource policy check</a> with <var>request</var> and <var>response</var>
 returns <b>blocked</b>, then return a <a>network error</a>.

 <li>
  <p>If <var>response</var>'s <a for=response>status</a> is <code>401</code>,
  <var>httpRequest</var>'s <a for=request>response tainting</a> is not "<code>cors</code>", the
  <i>credentials flag</i> is set, and <var>request</var>'s <a for=request>window</a> is an
  <a>environment settings object</a>, then:

  <ol>
   <li class=XXX><p>Needs testing: multiple `<code>WWW-Authenticate</code>` headers, missing,
   parsing issues.

   <li>
    <p>If <var>request</var>'s <a for=request>body</a> is non-null, then:

    <ol>
     <li><p>If <var>request</var>'s <a for=request>body</a>'s <a for=body>source</a> is null,
     then return a <a>network error</a>.

     <li><p>Set <var>request</var>'s <a for=request>body</a> to the first return value of
     <a for=BodyInit>safely extracting</a> <var>request</var>'s <a for=request>body</a>'s
     <a for=body>source</a>.
    </ol>

   <li>
    <p>If <var>request</var>'s <a for=request>use-URL-credentials flag</a> is unset or
    <i>authentication-fetch flag</i> is set, then:

    <ol>
     <li>
      <p>If the ongoing fetch is <a for=fetch>terminated</a>, then:

      <ol>
       <li><p>Let <var>aborted</var> be the termination's aborted flag.

       <li><p>If <var>aborted</var> is set, then return an <a>aborted network error</a>.

       <li><p>Return a <a>network error</a>.
      </ol>

     <li><p>Let <var>username</var> and <var>password</var> be the result of prompting the end user
     for a username and password, respectively, in <var>request</var>'s
     <a for=request>window</a>.

     <li><p><a>Set the username</a> given <var>request</var>'s <a for=request>current URL</a> and
     <var>username</var>.

     <li><p><a>Set the password</a> given <var>request</var>'s <a for=request>current URL</a> and
     <var>password</var>.
    </ol>

   <li><p>Set <var>response</var> to the result of performing an
   <a>HTTP-network-or-cache fetch</a> using
   <var>request</var> with <i>authentication-fetch flag</i> set.
  </ol>

 <li>
  <p>If <var>response</var>'s <a for=response>status</a> is <code>407</code>, then:

  <ol>
   <li><p>If <var>request</var>'s <a for=request>window</a> is
   "<code>no-window</code>", then return a <a>network error</a>.

   <li class=XXX><p>Needs testing: multiple `<code>Proxy-Authenticate</code>` headers, missing,
   parsing issues.

   <li>
    <p>If the ongoing fetch is <a for=fetch>terminated</a>, then:

    <ol>
     <li><p>Let <var>aborted</var> be the termination's aborted flag.

     <li><p>If <var>aborted</var> is set, then return an <a>aborted network error</a>.

     <li><p>Return a <a>network error</a>.
    </ol>

   <li>
    <p>Prompt the end user as appropriate in <var>request</var>'s
    <a for=request>window</a> and store the result as a
    <a>proxy-authentication entry</a>. [[!HTTP-AUTH]]

    <p class=note>Remaining details surrounding proxy authentication are defined by HTTP.

   <li><p>Set <var>response</var> to the result of performing an <a>HTTP-network-or-cache fetch</a>
   using <var>request</var>.
  </ol>

 <li><p>If <i>authentication-fetch flag</i> is set, then create an <a>authentication entry</a>
 for <var>request</var> and the given realm.

 <li><p>Return <var>response</var>. <span class="note no-backref">Typically
 <var>response</var>'s <a for=response>body</a>'s
 <a for=body>stream</a> is still being enqueued to after returning.</span>
</ol>


<h3 id=http-network-fetch>HTTP-network fetch</h3>

<p>To perform an <dfn id=concept-http-network-fetch>HTTP-network fetch</dfn> using
<var>request</var> with an optional <i>credentials flag</i>, run these steps:

<ol>
 <li><p>Let <var>credentials</var> be true if <i>credentials flag</i> is set, and false otherwise.

 <li><p>Let <var>response</var> be null.

 <li>
  <p>Switch on <var>request</var>'s <a for=request>mode</a>:

  <dl>
   <dt>"<code>websocket</code>"
   <dd><p>Let <var>connection</var> be the result of
   <a lt="obtain a WebSocket connection">obtaining a WebSocket connection</a>, given
   <var>request</var>'s <a for=request>current URL</a>.

   <dt>Otherwise
   <dd><p>Let <var>connection</var> be the result of
   <a lt="obtain a connection" for=connection>obtaining a connection</a>, given <var>request</var>'s
   <a for=request>current URL</a>'s <a for=url>origin</a> and <var>credentials</var>.
  </dl>


 <li>
  <p>Run these steps, but <a>abort when</a> the ongoing fetch is <a for=fetch>terminated</a>:

  <ol>
   <li><p>If <var>connection</var> is failure, return a
   <a>network error</a>.

   <li><p>If <var>connection</var> is not an HTTP/2 connection, <var>request</var>'s
   <a for=request>body</a> is non-null, and <var>request</var>'s <a for=request>body</a>'s
   <a for=body>source</a> is null, then <a for="header list">append</a>
   `<code>Transfer-Encoding</code>`/`<code>chunked</code>` to <var>request</var>'s
   <a for=request>header list</a>.

   <li>
    <p>Set <var>response</var> to the result of making an HTTP request over <var>connection</var>
    using <var>request</var> with the following caveats:

    <ul>
     <li><p>Follow the relevant requirements from HTTP. [[!HTTP]] [[!HTTP-SEMANTICS]] [[!HTTP-COND]] [[!HTTP-CACHING]] [[!HTTP-AUTH]]

     <li><p>Wait until all the <a for=/>headers</a> are transmitted.

     <li>
      <p>Any <a for=/>responses</a> whose
      <a for=response>status</a> is in the range <code>100</code> to
      <code>199</code>, inclusive, and is not <code>101</code>, are to be ignored.

      <p class="note no-backref">These kind of <a for=/>responses</a> are
      eventually followed by a "final" <a for=/>response</a>.
    </ul>

    <p class=note>The exact layering between Fetch and HTTP still needs to be sorted through and
    therefore <var>response</var> represents both a <a for=/>response</a> and
    an HTTP response here.

    <p>If <var>request</var>'s <a for=request>header list</a> contains
    `<code>Transfer-Encoding</code>`/`<code>chunked</code>` and <var>response</var> is transferred
    via HTTP/1.0 or older, then return a <a>network error</a>.

    <p>If the HTTP request results in a TLS client certificate dialog, then:

    <ol>
     <li><p>If <var>request</var>'s <a for=request>window</a>
     is an <a>environment settings object</a>, make the dialog
     available in <var>request</var>'s
     <a for=request>window</a>.

     <li><p>Otherwise, return a <a>network error</a>.
    </ol>

    <p>If <var>response</var> was retrieved over HTTPS, set its
    <a for=response>HTTPS state</a> to either
    "<code>deprecated</code>" or "<code>modern</code>".
    [[!TLS]]

    <p class="note no-backref">The exact determination here is up to user agents for the
    time being. User agents are strongly encouraged to only succeed HTTPS connections with
    strong security properties and return
    <a>network errors</a> otherwise. Using the
    "<code>deprecated</code>" state value ought to be a temporary and last resort kind
    of option.

    <p><a for=request>Transmit body</a> for <var>request</var>.
  </ol>

 <li>
  <p><a>If aborted</a>, then:

  <ol>
   <li><p>Let <var>aborted</var> be the termination's aborted flag.

   <li><p>If <var>connection</var> uses HTTP/2, then transmit an <code>RST_STREAM</code> frame.

   <li><p>If <var>aborted</var> is set, then return an <a>aborted network error</a>.

   <li><p>Return a <a>network error</a>.
  </ol>

 <li><p>Let <var>highWaterMark</var> be a non-negative, non-NaN number, chosen by the user agent.

 <li><p>Let <var>sizeAlgorithm</var> be an algorithm that accepts a <a>chunk</a> object and returns
 a non-negative, non-NaN, non-infinite number, chosen by the user agent.

 <li><p>Let <var>pull</var> be an action that <a lt=resumed for=fetch>resumes</a> the ongoing fetch
 if it is <a lt=suspend for=fetch>suspended</a>.

 <li><p>Let <var>cancel</var> be an action that <a lt=terminated for=fetch>terminates</a> the
 ongoing fetch with the aborted flag set.

 <li>
  <p>Let <var>stream</var> be the result of
  <a lt="construct a ReadableStream object" for=ReadableStream>constructing</a> a {{ReadableStream}}
  object with <var>highWaterMark</var>, <var>sizeAlgorithm</var>, <var>pull</var>, and
  <var>cancel</var>.

  <p class="note no-backref">This construction operation will not throw an exception.

 <li>
  <p>Run these steps, but <a>abort when</a> the ongoing fetch is <a for=fetch>terminated</a>:

  <ol>
   <li><p>Set <var>response</var>'s <a for=response>body</a> to a new
   <a for=/>body</a> whose <a for=body>stream</a> is
   <var>stream</var>.

   <li><p>If <var>response</var> has a payload body length, then set <var>response</var>'s
   <a for=response>body</a>'s
   <a for=body>total bytes</a> to that payload body length.
   <!-- XXX xref payload body -->

   <li><p>If <var>response</var> is not a
   <a>network error</a> and <var>request</var>'s
   <a for=request>cache mode</a> is not "<code>no-store</code>",
   update <var>response</var> in the HTTP cache for <var>request</var>.
   <!-- XXX xref HTTP cache -->

   <li>
    <p>If <i>credentials flag</i> is set and the user agent is not configured to block cookies for
    <var>request</var> (see <a href=https://tools.ietf.org/html/rfc6265#section-7>section 7</a> of
    [[!COOKIES]]), then run the "set-cookie-string" parsing algorithm (see <a
    href=https://tools.ietf.org/html/rfc6265#section-5.2>section 5.2</a> of [[!COOKIES]]) on the <a
    for=header>value</a> of each <var>header</var> whose <a for=header>name</a> is a
    <a>byte-case-insensitive</a> match for `<code>Set-Cookie</code>` in <var>response</var>'s <a
    for=response>header list</a>, if any, and <var>request</var>'s <a for=request>current URL</a>.

    <p class=note>This is a fingerprinting vector.
  </ol>

 <li>
  <p><a>If aborted</a>, then:

  <ol>
   <li><p>Let <var>aborted</var> be the termination's aborted flag.

   <li><p>If <var>aborted</var> is set, then set <var>response</var>'s
   <a for=response>aborted flag</a>.

   <li><p>Return <var>response</var>.
  </ol>

 <li>
  <p>Run these steps <a>in parallel</a>:

  <ol>
   <li>
    <p>Run these steps, but <a>abort when</a> the ongoing fetch is <a for=fetch>terminated</a>:

    <ol>
     <li>
      <p>While true:

      <ol>
       <li>
        <p>If one or more bytes have been transmitted from <var>response</var>'s message body, then:

        <ol>
         <li><p>Let <var>bytes</var> be the transmitted bytes.

         <li><p>Increase <var>response</var>'s <a for=response>body</a>'s <a for=body>transmitted
         bytes</a> with <var>bytes</var>' length.

         <li><p>Let <var>codings</var> be the result of <a>extracting header list values</a> given
         `<code>Content-Encoding</code>` and <var>response</var>'s <a for=response>header list</a>.

         <li>
          <p>Set <var>bytes</var> to the result of <a lt="handle content codings">handling content
          codings</a> given <var>codings</var> and <var>bytes</var>.

          <p class="note no-backref">This makes the `<code>Content-Length</code>` <a for=/>header</a>
          unreliable to the extent that it was reliable to begin with.

         <li><p>If <var>bytes</var> is failure, then <a lt=terminated for=fetch>terminate</a> the
         ongoing fetch.

         <li><p><a for=ReadableStream>Enqueue</a> a <code>Uint8Array</code> object wrapping an
         <code>ArrayBuffer</code> containing <var>bytes</var> to <var>stream</var>. If that threw an
         exception, <a lt=terminated for=fetch>terminate</a> the ongoing fetch, and
         <a abstract-op>error</a> <var>stream</var> with that exception.

         <li><p>If <var>stream</var> doesn't <a lt="need more data" for=ReadableStream>need more
         data</a> and <var>request</var>'s <a>synchronous flag</a> is unset, ask the user agent to
         <a for=fetch>suspend</a> the ongoing fetch.
        </ol>

       <li><p>Otherwise, if the bytes transmission for <var>response</var>'s message body is done
       normally and <var>stream</var> is <a for=ReadableStream>readable</a>, then
       <a abstract-op>close</a> <var>stream</var> and abort these in-parallel steps.
      </ol>
    </ol>

   <li>
    <p><a>If aborted</a>, then:

    <ol>
     <li><p>Let <var>aborted</var> be the termination's aborted flag.

     <li>
      <p>If <var>aborted</var> is set, then:

      <ol>
       <li><p>Set <var>response</var>'s <a for=response>aborted flag</a>.

       <li><p>If <var>stream</var> is <a for=ReadableStream>readable</a>, <a abstract-op>error</a>
       <var>stream</var> with an "<code><a exception>AbortError</a></code>" {{DOMException}}.
      </ol>

     <li><p>Otherwise, if <var>stream</var> is <a for=ReadableStream>readable</a>,
     <a abstract-op>error</a> <var>stream</var> with a {{TypeError}}.

     <li><p>If <var>connection</var> uses HTTP/2, then transmit an <code>RST_STREAM</code> frame.

     <li>
      <p>Otherwise, the user agent should close <var>connection</var> unless it would be bad for
      performance to do so.

      <p class=note>For instance, the user agent could keep the connection open if it knows there's
      only a few bytes of transfer remaining on a reusable connection. In this case it could be
      worse to close the connection and go through the handshake process again for the next fetch.
    </ol>
  </ol>

  <p class="note no-backref">These are run <a>in parallel</a> as at this point it is unclear whether
  <var>response</var>'s <a for=response>body</a> is relevant (<var>response</var> might be a
  redirect).

 <li><p>Return <var>response</var>. <span class="note no-backref">Typically <var>response</var>'s
 <a for=response>body</a>'s <a for=body>stream</a> is still being enqueued to after
 returning.</span>
</ol>


<h3 id=cors-preflight-fetch>CORS-preflight fetch</h3>

<p class="note no-backref">This is effectively the user agent implementation of the check to see if
the <a>CORS protocol</a> is understood. The so-called <a>CORS-preflight request</a>. If
successful it populates the <a>CORS-preflight cache</a> to minimize the
number of these <a lt="CORS-preflight fetch">fetches</a>.

<p>To perform a <dfn id=cors-preflight-fetch-0>CORS-preflight fetch</dfn> using <var>request</var>,
run these steps:

<ol>
 <li>
  <p>Let <var>preflight</var> be a new <a for=/>request</a> whose
  <a for=request>method</a> is `<code>OPTIONS</code>`,
  <a for=request>URL</a> is <var>request</var>'s <a for=request>current URL</a>,
  <a for=request>initiator</a> is <var>request</var>'s <a for=request>initiator</a>,
  <a for=request>destination</a> is <var>request</var>'s <a for=request>destination</a>,
  <a for=request>origin</a> is <var>request</var>'s <a for=request>origin</a>,
  <a for=request>referrer</a> is <var>request</var>'s <a for=request>referrer</a>,
  <a for=request>referrer policy</a> is <var>request</var>'s <a for=request>referrer policy</a>,
  <a for=request>mode</a> is "<code>cors</code>",
  <a for=request>tainted origin flag</a> is <var>request</var>'s
  <a for=request>tainted origin flag</a>, and
  <a for=request>response tainting</a> is "<code>cors</code>".

  <p class="note no-backref">The <a for=request>service-workers mode</a> of <var>preflight</var>
  does not matter as this algorithm uses <a>HTTP-network-or-cache fetch</a> rather than
  <a>HTTP fetch</a>.

 <li><p><a for="header list">Append</a> `<code>Accept</code>`/`<code>*/*</code>` to
 <var>preflight</var>'s <a for=request>header list</a>.

 <li><p><a for="header list">Append</a> `<a http-header><code>Access-Control-Request-Method</code></a>`
 to <var>request</var>'s <a for=request>method</a> in <var>preflight</var>'s
 <a for=request>header list</a>.

 <li><p>Let <var>headers</var> be the <a>CORS-unsafe request-header names</a> with
 <var>request</var>'s <a for=request>header list</a>.

 <li>
  <p>If <var>headers</var> <a for=list>is not empty</a>, then:

  <ol>
   <li><p>Let <var>value</var> be the items in <var>headers</var> separated from each other by
   `<code>,</code>`.

   <li><p><a for="header list">Append</a>
   `<a http-header><code>Access-Control-Request-Headers</code></a>` to <var>value</var> in
   <var>preflight</var>'s <a for=request>header list</a>.
  </ol>

  <p class=note>This intentionally does not use <a for="header list">combine</a>, as 0x20 following
  0x2C is not the way this was implemented, for better or worse.

 <li><p>Let <var>response</var> be the result of performing an <a>HTTP-network-or-cache fetch</a>
 using <var>preflight</var>.

 <li>
  <p>If a <a>CORS check</a> for <var>request</var> and <var>response</var> returns success and
  <var>response</var>'s <a for=response>status</a> is an <a>ok status</a>, then:
  <!-- CORS said 200 here but nobody implemented that:
       https://lists.w3.org/Archives/Public/public-webappsec/2013Feb/0078.html -->

  <p class="note no-backref">The <a>CORS check</a> is done on <var>request</var> rather than
  <var>preflight</var> to ensure the correct <a for=request>credentials mode</a> is used.

  <ol>
   <li><p>Let <var>methods</var> be the result of <a>extracting header list values</a> given
   `<a http-header><code>Access-Control-Allow-Methods</code></a>` and <var>response</var>'s
   <a for=response>header list</a>.

   <li><p>Let <var>headerNames</var> be the result of <a>extracting header list values</a> given
   `<a http-header><code>Access-Control-Allow-Headers</code></a>` and <var>response</var>'s
   <a for=response>header list</a>.

   <li><p>If either <var>methods</var> or <var>headerNames</var> is failure,
   return a <a>network error</a>.

   <li>
    <p>If <var>methods</var> is null and <var>request</var>'s <a>use-CORS-preflight flag</a>
    is set, then set <var>methods</var> to a new list containing <var>request</var>'s
    <a for=request>method</a>.

    <p class="note no-backref">This ensures that a <a>CORS-preflight fetch</a> that
    happened due to <var>request</var>'s <a>use-CORS-preflight flag</a> being set is
    <a lt="CORS-preflight cache">cached</a>.

   <li><p>If <var>request</var>'s <a for=request>method</a> is not in <var>methods</var>,
   <var>request</var>'s <a for=request>method</a> is not a <a>CORS-safelisted method</a>, and
   <var>request</var>'s <a for=request>credentials mode</a> is "<code>include</code>" or
   <var>methods</var> does not contain `<code>*</code>`, then return a <a>network error</a>.

   <li><p>If one of <var>request</var>'s <a for=request>header list</a>'s
   <a lt=name for=header>names</a> is a <a>CORS non-wildcard request-header name</a> and is not a
   <a>byte-case-insensitive</a> match for an <a for=list>item</a> in <var>headerNames</var>, then
   return a <a>network error</a>.

   <li><p><a for=list>For each</a> <var>unsafeName</var> in the
   <a>CORS-unsafe request-header names</a> with <var>request</var>'s
   <a for=request>header list</a>, if <var>unsafeName</var> is not a <a>byte-case-insensitive</a>
   match for an <a for=list>item</a> in <var>headerNames</var> and <var>request</var>'s
   <a for=request>credentials mode</a> is "<code>include</code>" or <var>headerNames</var> does not
   contain `<code>*</code>`, return a <a>network error</a>.

   <li><p>Let <var>max-age</var> be the result of <a>extracting header list values</a> given
   `<a http-header><code>Access-Control-Max-Age</code></a>` and <var>response</var>'s
   <a for=response>header list</a>.

   <li><p>If <var>max-age</var> is failure or null, then set <var>max-age</var> to zero.

   <li><p>If <var>max-age</var> is greater than an imposed limit on
   <a for="cache entry">max-age</a>, then set <var>max-age</var> to the imposed limit.

   <li><p>If the user agent does not provide for a <a lt="CORS-preflight cache">cache</a>, then
   return <var>response</var>.

   <li><p>For each <var>method</var> in <var>methods</var> for which there is a
   <a>method cache entry match</a> using <var>request</var>, set matching entry's
   <a for="cache entry">max-age</a> to <var>max-age</var>.

   <li><p>For each <var>method</var> in <var>methods</var> for which there is no
   <a>method cache entry match</a> using <var>request</var>, <a>create a new cache entry</a> with
   <var>request</var>, <var>max-age</var>, <var>method</var>, and null.

   <li><p>For each <var>headerName</var> in <var>headerNames</var> for which there is a
   <a>header-name cache entry match</a> using <var>request</var>, set matching entry's
   <a for="cache entry">max-age</a> to <var>max-age</var>.

   <li><p>For each <var>headerName</var> in <var>headerNames</var> for which there is no
   <a>header-name cache entry match</a> using <var>request</var>, <a>create a new cache entry</a>
   with <var>request</var>, <var>max-age</var>, null, and <var>headerName</var>.

   <li><p>Return <var>response</var>.
  </ol>

 <li><p>Otherwise, return a <a>network error</a>.
</ol>

<h3 id=cors-preflight-cache>CORS-preflight cache</h3>

<p>A user agent has an associated <a>CORS-preflight cache</a>. A
<dfn id=concept-cache>CORS-preflight cache</dfn> is a <a for=/>list</a> of <a>cache entries</a>.

<p>A <dfn>cache entry</dfn> consists of:

<ul class=brief>
 <li><dfn id=concept-cache-origin for="cache entry">byte-serialized origin</dfn> (a
 <a for=/>byte sequence</a>)
 <li><dfn id=concept-cache-url for="cache entry">URL</dfn> (a <a for=/>URL</a>)
 <li><dfn id=concept-cache-max-age for="cache entry">max-age</dfn> (a number of seconds)
 <li><dfn id=concept-cache-credentials for="cache entry">credentials</dfn> (a boolean)
 <li><dfn id=concept-cache-method for="cache entry">method</dfn> (null, `<code>*</code>`, or a
 <a for=/>method</a>)
 <li><dfn id=concept-cache-header-name for="cache entry">header name</dfn> (null, `<code>*</code>`,
 or a <a for=/>header</a> <a for=header>name</a>)
</ul>

<p><a>Cache entries</a> must be removed after the seconds specified in their
<a for="cache entry">max-age</a> field have passed since storing the entry. <a>Cache entries</a> may
be removed before that moment arrives.

<p>To <dfn id=concept-cache-create-entry>create a new cache entry</dfn>, given <var>request</var>,
<var>max-age</var>, <var>method</var>, and <var>headerName</var>, run these steps:

<ol>
 <li>
  <p>Let <var>entry</var> be a <a>cache entry</a>, initialized as follows:

  <dl>
   <dt><a for="cache entry">byte-serialized origin</a>
   <dd><p>The result of <a>byte-serializing a request origin</a> with <var>request</var>

   <dt><a for="cache entry">URL</a>
   <dd><p><var>request</var>'s <a for=request>current URL</a>

   <dt><a for="cache entry">max-age</a>
   <dd><p><var>max-age</var>

   <dt><a for="cache entry">credentials</a>
   <dd><p>True if <var>request</var>'s <a for=request>credentials mode</a> is
   "<code>include</code>", and false otherwise

   <dt><a for="cache entry">method</a>
   <dd><p><var>method</var>

   <dt><a for="cache entry">header name</a>
   <dd><p><var>headerName</var>
  </dl>

 <li><p><a for=list>Append</a> <var>entry</var> to the user agent's <a>CORS-preflight cache</a>.
</ol>

<p>To <dfn id=concept-cache-clear>clear cache entries</dfn>, given a <var>request</var>,
<a for=list>remove</a> any <a>cache entries</a> in the user agent's <a>CORS-preflight cache</a>
whose <a for="cache entry">byte-serialized origin</a> is the result of
<a>byte-serializing a request origin</a> with <var>request</var> and whose
<a for="cache entry">URL</a> is <var>request</var>'s <a for=request>current URL</a>.

<p>There is a <dfn id=concept-cache-match>cache entry match</dfn> for a <a>cache entry</a>
<var>entry</var> with <var>request</var> if <var>entry</var>'s
<a for="cache entry">byte-serialized origin</a> is the result of
<a>byte-serializing a request origin</a> with <var>request</var>, <var>entry</var>'s
<a for="cache entry">URL</a> is <var>request</var>'s <a for=request>current URL</a>, and one of

<ul class=brief>
 <li><var>entry</var>'s <a for="cache entry">credentials</a> is true
 <li><var>entry</var>'s <a for="cache entry">credentials</a> is false and <var>request</var>'s
 <a for=request>credentials mode</a> is not "<code>include</code>".
</ul>

<p>is true.

<p>There is a <dfn id=concept-cache-match-method>method cache entry match</dfn> for
<var>method</var> using <var>request</var> when there is a <a>cache entry</a> in the user agent's
<a>CORS-preflight cache</a> for which there is a <a>cache entry match</a> with <var>request</var>
and its <a for="cache entry">method</a> is <var>method</var> or `<code>*</code>`.

<p>There is a <dfn id=concept-cache-match-header>header-name cache entry match</dfn> for
<var>headerName</var> using <var>request</var> when there is a <a>cache entry</a> in the user
agent's <a>CORS-preflight cache</a> for which there is a <a>cache entry match</a> with
<var>request</var> and one of

<ul class=brief>
 <li>its <a for="cache entry">header name</a> is a <a>byte-case-insensitive</a> match for
 <var>headerName</var>
 <li>its <a for="cache entry">header name</a> is `<code>*</code>` and <var>headerName</var> is not
 a <a>CORS non-wildcard request-header name</a>
</ul>

<p>is true.


<h3 id=cors-check>CORS check</h3>

<p>To perform a <dfn id=concept-cors-check>CORS check</dfn> for a <var>request</var> and
<var>response</var>, run these steps:

<ol>
 <li><p>Let <var>origin</var> be the result of <a for="header list">getting</a>
 `<a http-header><code>Access-Control-Allow-Origin</code></a>` from <var>response</var>'s
 <a for=response>header list</a>.

 <li>
  <p>If <var>origin</var> is null, then return failure.

  <p class=note>Null is not `<code>null</code>`.

 <li><p>If <var>request</var>'s <a for=request>credentials mode</a> is not "<code>include</code>"
 and <var>origin</var> is `<code>*</code>`, then return success.

 <li><p>If the result of <a>byte-serializing a request origin</a> with <var>request</var> is not
 <var>origin</var>, then return failure.

 <li><p>If <var>request</var>'s <a for=request>credentials mode</a> is not "<code>include</code>",
 then return success.

 <li><p>Let <var>credentials</var> be the result of <a for="header list">getting</a>
 `<a http-header><code>Access-Control-Allow-Credentials</code></a>` from <var>response</var>'s
 <a for=response>header list</a>.

 <li><p>If <var>credentials</var> is `<code>true</code>`, then return success.

 <li><p>Return failure.
</ol>


<h3 id=tao-check>TAO check</h3>

<p>To perform a <dfn id=concept-tao-check>TAO check</dfn> for a <var>request</var> and
<var>response</var>, run these steps:

<ol>
 <li><p>If <var>request</var>'s <a for=request>timing allow failed flag</a> is set, then return
 failure.

 <li><p>If <var>request</var>'s <a for=request>response tainting</a> is "<code>basic</code>", then
 return success.

 <li><p>Let <var>values</var> be the result of
 <a for="header list">getting, decoding, and splitting</a> `<code>Timing-Allow-Origin</code>` from
 <var>response</var>'s <a for=response>header list</a>.

 <li><p>If <var>values</var> <a for=list>contains</a> "<code>*</code>", then return success.

 <li><p>If <var>values</var> <a for=list>contains</a> the result of
 <a>serializing a request origin</a> with <var>request</var>, then return success.

 <li><p>Return failure.
</ol>



<h2 id=fetch-api>Fetch API</h2>

<p class=no-backref>The <a><code>fetch()</code></a> method is relatively
low-level API for <a lt=fetch for=/>fetching</a> resources. It covers slightly
more ground than {{XMLHttpRequest}}, although it is
currently lacking when it comes to request progression (not response progression).

<div id=fetch-blob-example class="example no-backref">
 <p>The <a><code>fetch()</code></a> method makes it quite straightforward
 to <a for=/>fetch</a> a resource and extract its contents as a
 {{Blob}}:

 <pre><code class=lang-javascript>
fetch("/music/pk/altes-kamuffel.flac")
  .then(res => res.blob()).then(playBlob)
</code></pre>

 <p>If you just care to log a particular response header:

 <pre><code class=lang-javascript>
fetch("/", {method:"HEAD"})
  .then(res => log(res.headers.get("strict-transport-security")))
</code></pre>

 <p>If you want to check a particular response header and then process the response of a
 cross-origin resources:

 <pre><code class=lang-javascript>
fetch("https://pk.example/berlin-calling.json", {mode:"cors"})
  .then(res => {
    if(res.headers.get("content-type") &amp;&amp;
       res.headers.get("content-type").toLowerCase().indexOf("application/json") >= 0) {
      return res.json()
    } else {
      throw new TypeError()
    }
  }).then(processJSON)
</code></pre>

 <p>If you want to work with URL query parameters:

 <pre><code class=lang-javascript>
var url = new URL("https://geo.example.org/api"),
    params = {lat:35.696233, long:139.570431}
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]))
fetch(url).then(/* … */)
</code></pre>

 <p>If you want to receive the body data progressively:

 <pre><code class=lang-javascript>
function consume(reader) {
  var total = 0
  return pump()
  function pump() {
    return reader.read().then(({done, value}) => {
      if (done) {
        return
      }
      total += value.byteLength
      log(`received ${value.byteLength} bytes (${total} bytes in total)`)
      return pump()
    })
  }
}

fetch("/music/pk/altes-kamuffel.flac")
  .then(res => consume(res.body.getReader()))
  .then(() => log("consumed the entire body without keeping the whole thing in memory!"))
  .catch(e => log("something went wrong: " + e))
</code></pre>
</div>


<h3 id=headers-class>Headers class</h3>

<pre class=idl>
typedef (sequence&lt;sequence&lt;ByteString>> or record&lt;ByteString, ByteString>) HeadersInit;

[Exposed=(Window,Worker)]
interface Headers {
  constructor(optional HeadersInit init);

  void append(ByteString name, ByteString value);
  void delete(ByteString name);
  ByteString? get(ByteString name);
  boolean has(ByteString name);
  void set(ByteString name, ByteString value);
  iterable&lt;ByteString, ByteString>;
};
</pre>

<p class=note>Unlike a <a for=/>header list</a>, a {{Headers}} object cannot represent more than one
`<code>Set-Cookie</code>` <a for=/>header</a>. In a way this is problematic as unlike all other
headers `<code>Set-Cookie</code>` headers cannot be combined, but since `<code>Set-Cookie</code>`
headers are not exposed to client-side JavaScript this is deemed an acceptable compromise.
Implementations could chose the more efficient {{Headers}} object representation even for a
<a for=/>header list</a>, as long as they also support an associated data structure for
`<code>Set-Cookie</code>` headers.

<div class=example id=example-headers-class>
 <p>A {{Headers}} object can be initialized with various JavaScript data structures:

 <pre><code class=lang-javascript>
var meta = { "Content-Type": "text/xml", "Breaking-Bad": "&lt;3" }
new Headers(meta)

// The above is equivalent to
var meta = [
  [ "Content-Type", "text/xml" ],
  [ "Breaking-Bad", "&lt;3" ]
]
new Headers(meta)
</code></pre>
</div>

<p>A {{Headers}} object has an associated
<dfn export for=Headers id=concept-headers-header-list>header list</dfn> (a
<a for=/>header list</a>), which is initially empty. <span class=note>This
can be a pointer to the <a for=/>header list</a> of something else, e.g.,
of a <a for=/>request</a> as demonstrated by {{Request}}
objects.</span>

<p>A {{Headers}} object also has an associated
<dfn export for=Headers id=concept-headers-guard>guard</dfn>, which is
"<code>immutable</code>",
"<code>request</code>",
"<code>request-no-cors</code>",
"<code>response</code>" or
"<code>none</code>".

<p>To <dfn export for=Headers id=concept-headers-append>append</dfn> a
<a for=header>name</a>/<a for=header>value</a>
<var>name</var>/<var>value</var> pair to a
{{Headers}} object (<var>headers</var>), run these steps:

<ol>
 <li><p><a lt=normalize for=header/value>Normalize</a> <var>value</var>.

 <li><p>If <var>name</var> is not a <a for=header>name</a> or <var>value</var> is not a
 <a for=header>value</a>, then <a>throw</a> a {{TypeError}}.

 <li><p>If <var>headers</var>'s <a for=Headers>guard</a> is "<code>immutable</code>", then
 <a>throw</a> a {{TypeError}}.

 <li><p>Otherwise, if <var>headers</var>'s <a for=Headers>guard</a> is "<code>request</code>" and
 <var>name</var> is a <a>forbidden header name</a>, return.

 <li>
  <p>Otherwise, if <var>headers</var>'s <a for=Headers>guard</a> is "<code>request-no-cors</code>":

  <ol>
   <li><p>Let <var>temporaryValue</var> be the result of <a for="header list">getting</a>
   <var>name</var> from <var>headers</var>'s <a for=Headers>header list</a>.

   <li><p>If <var>temporaryValue</var> is null, then set <var>temporaryValue</var> to
   <var>value</var>.

   <li><p>Otherwise, set <var>temporaryValue</var> to <var>temporaryValue</var>, followed by
   0x2C 0x20, followed by <var>value</var>.

   <li><p>If <var>name</var>/<var>temporaryValue</var> is not a
   <a>no-CORS-safelisted request-header</a>, then return.
  </ol>

 <li><p>Otherwise, if <var>headers</var>'s <a for=Headers>guard</a> is "<code>response</code>" and
 <var>name</var> is a <a>forbidden response-header name</a>, return.

 <li><p><a for="header list">Append</a> <var>name</var>/<var>value</var> to <var>headers</var>'s
 <a for=Headers>header list</a>.

 <li><p>If <var>headers</var>'s <a for=Headers>guard</a> is "<code>request-no-cors</code>", then
 <a for=Headers>remove privileged no-CORS request headers</a> from <var>headers</var>.
</ol>

<p>To <dfn export for=Headers id=concept-headers-fill>fill</dfn> a
{{Headers}} object (<var>headers</var>) with a given object (<var>object</var>),
run these steps:

<ol>
 <li>
  <p>If <var>object</var> is a <a>sequence</a>, then <a for=list>for each</a> <var>header</var> in
  <var>object</var>:

  <ol>
   <li><p>If <var>header</var> does not contain exactly two items, then <a>throw</a> a
   {{TypeError}}.

   <li><p><a lt=append for=Headers>Append</a> <var>header</var>'s first item/<var>header</var>'s
   second item to <var>headers</var>.
  </ol>

 <li><p>Otherwise, <var>object</var> is a <a for=/>record</a>, then <a for=map>for each</a>
 <var>key</var> → <var>value</var> in <var>object</var>, <a lt=append for=Headers>append</a>
 <var>key</var>/<var>value</var> to <var>headers</var>.
</ol>

<p>To
<dfn for=Headers id=concept-headers-remove-privileged-no-cors-request-headers>remove privileged no-CORS request headers</dfn>
from a {{Headers}} object (<var>headers</var>), run these steps:

<ol>
 <li><p><a for="list">For each</a> <var>headerName</var> of
 <a>privileged no-CORS request-header names</a>:

 <ol>
  <li><p><a for="header list">Delete</a> <var>headerName</var> from <var>headers</var>'s
  <a for=Headers>header list</a>.
 </ol>
</ol>

<p class=note>This is called when headers are modified by unprivileged code.

<p>The
<dfn id=dom-headers export for=Headers constructor><code>Headers(<var>init</var>)</code></dfn>
constructor, when invoked, must run these steps:

<ol>
 <li><p>Let <var>headers</var> be a new {{Headers}} object whose
 <a for=Headers>guard</a> is "<code>none</code>".

 <li><p>If <var>init</var> is given, then <a for=Headers>fill</a> <var>headers</var> with
 <var>init</var>.

 <li><p>Return <var>headers</var>.
</ol>

<p>The <dfn export for=Headers method><code>append(<var>name</var>, <var>value</var>)</code></dfn>
method, when invoked, must <a for=Headers>append</a> <var>name</var>/<var>value</var> to the
<a>context object</a>.

<p>The <dfn export for=Headers method><code>delete(<var>name</var>)</code></dfn>
method, when invoked, must run these steps:

<ol>
 <li><p>If <var>name</var> is not a <a for=header>name</a>, then <a>throw</a> a {{TypeError}}.

 <li><p>If the <a>context object</a>'s <a for=Headers>guard</a> is "<code>immutable</code>", then
 <a>throw</a> a {{TypeError}}.

 <li><p>Otherwise, if the <a>context object</a>'s <a for=Headers>guard</a> is "<code>request</code>"
 and <var>name</var> is a <a>forbidden header name</a>, return.

 <li><p>Otherwise, if the <a>context object</a>'s <a for=Headers>guard</a> is
 "<code>request-no-cors</code>", <var>name</var> is not a
 <a>no-CORS-safelisted request-header name</a>, and <var>name</var> is not a
 <a>privileged no-CORS request-header name</a>, return.

 <li><p>Otherwise, if the <a>context object</a>'s <a for=Headers>guard</a> is
 "<code>response</code>" and <var>name</var> is a <a>forbidden response-header name</a>, return.

 <li><p>If the <a>context object</a>'s <a for=Headers>header list</a> does not
 <a for="header list">contain</a> <var>name</var>, then return.

 <li><p><a for="header list">Delete</a> <var>name</var> from the <a>context object</a>'s
 <a for=Headers>header list</a>.

 <li><p>If the <a>context object</a>'s <a for=Headers>guard</a> is "<code>request-no-cors</code>",
 then <a for=Headers>remove privileged no-CORS request headers</a> from the <a>context object</a>.
</ol>

<p>The <dfn export for=Headers method><code>get(<var>name</var>)</code></dfn> method, when
invoked, must run these steps:

<ol>
 <li><p>If <var>name</var> is not a <a for=header>name</a>, then <a>throw</a> a {{TypeError}}.

 <li><p>Return the result of <a for="header list">getting</a> <var>name</var> from the
 <a>context object</a>'s <a for=Headers>header list</a>.
</ol>

<p>The <dfn export for=Headers method><code>has(<var>name</var>)</code></dfn> method,
when invoked, must run these steps:

<ol>
 <li><p>If <var>name</var> is not a <a for=header>name</a>, then <a>throw</a> a {{TypeError}}.

 <li><p>Return true if the <a>context object</a>'s <a for=Headers>header list</a>
 <a for="header list">contains</a> <var>name</var>, and false otherwise.
</ol>

<p>The
<dfn export for=Headers method><code>set(<var>name</var>, <var>value</var>)</code></dfn>
method, when invoked, must run these steps:

<ol>
 <li><p><a lt=normalize for=header/value>Normalize</a> <var>value</var>.

 <li><p>If <var>name</var> is not a <a for=header>name</a> or <var>value</var> is not a
 <a for=header>value</a>, then <a>throw</a> a {{TypeError}}.

 <li><p>If the <a>context object</a>'s <a for=Headers>guard</a> is "<code>immutable</code>", then
 <a>throw</a> a {{TypeError}}.

 <li><p>Otherwise, if the <a>context object</a>'s <a for=Headers>guard</a> is "<code>request</code>"
 and <var>name</var> is a <a>forbidden header name</a>, return.

 <li><p>Otherwise, if the <a>context object</a>'s <a for=Headers>guard</a> is
 "<code>request-no-cors</code>" and <var>name</var>/<var>value</var> is not a
 <a>no-CORS-safelisted request-header</a>, return.

 <li><p>Otherwise, if the <a>context object</a>'s <a for=Headers>guard</a> is
 "<code>response</code>" and <var>name</var> is a <a>forbidden response-header name</a>, return.

 <li><p><a for="header list">Set</a> <var>name</var>/<var>value</var> in the <a>context object</a>'s
 <a for=Headers>header list</a>.

 <li><p>If the <a>context object</a>'s <a for=Headers>guard</a> is "<code>request-no-cors</code>",
 then <a for=Headers>remove privileged no-CORS request headers</a> from the <a>context object</a>.
</ol>

<p>The <a>value pairs to iterate over</a> are the return value of running
<a for="header list">sort and combine</a> with the <a>context object</a>'s
<a for=Headers>header list</a>.


<h3 id=body-mixin>Body mixin</h3>

<pre class=idl>
typedef (Blob or BufferSource or FormData or URLSearchParams or ReadableStream or USVString) BodyInit;</pre>

<p>To <dfn for=BodyInit export>safely extract</dfn> a <a for=/>body</a> and a
`<code>Content-Type</code>` <a for=header>value</a> from <var>object</var>, run these steps:

<ol>
 <li>
  <p>If <var>object</var> is a {{ReadableStream}} object, then:

  <ol>
   <li><p>Assert: <var>object</var> is neither <a for=ReadableStream>disturbed</a> nor
   <a for=ReadableStream>locked</a>.
  </ol>

 <li><p>Return the results of <a for=BodyInit>extracting</a> <var>object</var>.
</ol>

<p class="note no-backref">The <a for=BodyInit>safely extract</a> operation is a subset of the
<a for=BodyInit>extract</a> operation that is guaranteed to not throw an exception.

<p>To <dfn id=concept-bodyinit-extract for=BodyInit export>extract</dfn> a <a for=/>body</a> and a
`<code>Content-Type</code>` <a for=header>value</a> from
<var>object</var>, with an optional <var>keepalive flag</var>, run these steps:

<ol>
 <li><p>Let <var>stream</var> be the result of
 <a lt="construct a ReadableStream object" for=ReadableStream>constructing</a> a
 {{ReadableStream}} object.

 <li><p>Let <var>Content-Type</var> be null.

 <li><p>Let <var>action</var> be null.

 <li><p>Let <var>source</var> be null.

 <li>
  <p>Switch on <var>object</var>'s type:

  <dl class=switch>
   <dt>{{Blob}}
   <dd>
    <p>Set <var>action</var> to an action that reads <var>object</var>.

    <p>If <var>object</var>'s {{Blob/type}}
    attribute is not the empty byte sequence, set <var>Content-Type</var> to its value.

    <p>Set <var>source</var> to <var>object</var>.

   <dt><code>BufferSource</code>
   <dd>
    <p><a for=ReadableStream>Enqueue</a> a <code>Uint8Array</code> object
    wrapping an <code>ArrayBuffer</code> containing a copy of the bytes held by <var>object</var>
    to <var>stream</var> and <a abstract-op>close</a>
    <var>stream</var>. If that threw an exception,
    <a abstract-op>error</a> <var>stream</var> with that exception.

    <p>Set <var>source</var> to <var>object</var>.

   <dt>{{FormData}}
   <dd>
    <p>Set <var>action</var> to an action that runs the
    <a><code>multipart/form-data</code> encoding algorithm</a>, with <var>object</var> as
    <var ignore>form data set</var> and with <a>UTF-8</a> as the explicit character encoding.
    <!-- need to provide explicit character encoding because otherwise the encoding of the
         document is used -->

    <p>Set <var>Content-Type</var> to `<code>multipart/form-data; boundary=</code>`, followed by the
    <a><code>multipart/form-data</code> boundary string</a> generated by the
    <a><code>multipart/form-data</code> encoding algorithm</a>.

    <p>Set <var>source</var> to <var>object</var>.

   <dt>{{URLSearchParams}}
   <dd>
    <p>Set <var>action</var> to an action that runs the
    <a lt="urlencoded serializer"><code>application/x-www-form-urlencoded</code>
    serializer</a> with <var>object</var>'s
    <a for=URLSearchParams>list</a>.
    <!-- UTF-8 implied -->

    <p>Set <var>Content-Type</var> to
    `<code>application/x-www-form-urlencoded;charset=UTF-8</code>`.

    <p>Set <var>source</var> to <var>object</var>.

   <dt><code>USVString</code>
   <dd>
    <p>Set <var>action</var> to an action that runs <a>UTF-8 encode</a> on <var>object</var>.

    <p>Set <var>Content-Type</var> to `<code>text/plain;charset=UTF-8</code>`.

    <p>Set <var>source</var> to <var>object</var>.

   <dt>{{ReadableStream}}
   <dd>
    <p>If the <var>keepalive flag</var> is set, then <a>throw</a> a {{TypeError}}.

    <p>If <var>object</var> is <a for=ReadableStream>disturbed</a> or
    <a for=ReadableStream>locked</a>, then <a>throw</a> a {{TypeError}}.

    <p>Set <var>stream</var> to <var>object</var>.
  </dl>

 <li>
  <p>If <var>action</var> is non-null, run <var>action</var> <a>in parallel</a>:

  <ol>
   <li><p>Whenever one or more bytes are available, let <var>bytes</var> be the bytes and
   <a for=ReadableStream>enqueue</a> a <code>Uint8Array</code> object
   wrapping an <code>ArrayBuffer</code> containing <var>bytes</var> to <var>stream</var>. If
   creating the <code>ArrayBuffer</code> threw an exception,
   <a abstract-op>error</a> <var>stream</var> with that exception
   and cancel running <var>action</var>.

   <li><p>When running <var>action</var> is done,
   <a abstract-op>close</a> <var>stream</var>.
  </ol>

 <li><p>Let <var>body</var> be a <a for=/>body</a> whose <a for=body>stream</a> is
 <var>stream</var> and whose <a for=body>source</a> is <var>source</var>.

 <li><p>Return <var>body</var> and <var>Content-Type</var>.
</ol>


<pre class=idl>
interface mixin Body {
  readonly attribute ReadableStream? body;
  readonly attribute boolean bodyUsed;
  [NewObject] Promise&lt;ArrayBuffer> arrayBuffer();
  [NewObject] Promise&lt;Blob> blob();
  [NewObject] Promise&lt;FormData> formData();
  [NewObject] Promise&lt;any> json();
  [NewObject] Promise&lt;USVString> text();
};</pre>

<p class=note>Formats you would not want a network layer to be dependent upon, such as
HTML, will likely not be exposed here. Rather, an HTML parser API might accept a stream in
due course.
<!-- https://lists.w3.org/Archives/Public/public-whatwg-archive/2014Jun/thread.html#msg72 -->

<p>Objects implementing the {{Body}} mixin gain an associated
<dfn id=concept-body-body for=Body>body</dfn> (null or a <a for=/>body</a>) and
a <dfn id=concept-body-mime-type for=Body>MIME type</dfn> (failure or a <a for=/>MIME type</a>).

<p>An object implementing the {{Body}} mixin is said to be
<dfn export id=concept-body-disturbed for=Body>disturbed</dfn> if <a for=Body>body</a> is
non-null and its <a for=body>stream</a> is
<a for=ReadableStream>disturbed</a>.

<p>An object implementing the {{Body}} mixin is said to be
<dfn export id=concept-body-locked for=Body>locked</dfn> if <a for=Body>body</a> is
non-null and its <a for=body>stream</a> is
<a for=ReadableStream>locked</a>.

<p>The <dfn attribute for=Body><code>body</code></dfn> attribute's getter must return null if
<a for=Body>body</a> is null and <a for=Body>body</a>'s <a for=body>stream</a> otherwise.

<p>The <dfn attribute for=Body><code>bodyUsed</code></dfn> attribute's getter must
return true if <a for=Body>disturbed</a>, and false otherwise.

<p>Objects implementing the {{Body}} mixin also have an associated
<dfn id=concept-body-package-data for=Body>package data</dfn> algorithm, given
<var>bytes</var>, a <var>type</var> and a <var>mimeType</var>, switches on <var>type</var>, and
runs the associated steps:

<dl class=switch>
 <dt><i>ArrayBuffer</i>
 <dd>
  <p>Return a new <code>ArrayBuffer</code> whose contents are <var>bytes</var>.

  <p class="note">Allocating an <code>ArrayBuffer</code> can throw a {{RangeError}}.

 <dt><i>Blob</i>
 <dd><p>Return a {{Blob}} whose contents are <var>bytes</var> and {{Blob/type}} attribute is
 <var>mimeType</var>.

 <dt><i>FormData</i>
 <dd>
  <p>If <var>mimeType</var>'s <a for="MIME type">essence</a> is "<code>multipart/form-data</code>",
  then:

  <ol>
   <li>
    <p>Parse <var>bytes</var>, using the value of the `<code>boundary</code>` parameter from
    <var>mimeType</var>, per the rules set forth in
    <cite>Returning Values from Forms: multipart/form-data</cite>. [[!RFC7578]]</p>

    <p>Each part whose `<code>Content-Disposition</code>` header contains a `<code>filename</code>`
    parameter must be parsed into an <a for=FormData>entry</a> whose value is a {{File}} object
    whose contents are the contents of the part. The {{File/name}} attribute of the {{File}} object
    must have the value of the `<code>filename</code>` parameter of the part. The {{Blob/type}}
    attribute of the {{File}} object must have the value of the `<code>Content-Type</code>` header
    of the part if the part has such header, and `<code>text/plain</code>` (the default defined by
    [[!RFC7578]] section 4.4) otherwise.</p>

    <p>Each part whose `<code>Content-Disposition</code>` header does not contain a
    `<code>filename</code>` parameter must be parsed into an <a for=FormData>entry</a> whose value
    is the <a lt="UTF-8 decode without BOM">UTF-8 decoded without BOM</a> content of the part.
    <span class=note>This is done regardless of the presence or the value of a
    `<code>Content-Type</code>` header and regardless of the presence or the value of a
    `<code>charset</code>` parameter.</span></p>

    <p class=note>A part whose `<code>Content-Disposition</code>` header contains a
    `<code>name</code>` parameter whose value is `<code>_charset_</code>` is parsed like any other
    part. It does not change the encoding.</p>
   </li>

   <li><p>If that fails for some reason, then <a>throw</a> a {{TypeError}}.

   <li><p>Return a new {{FormData}} object, appending each <a for=FormData>entry</a>, resulting from
   the parsing operation, to <a for=FormData>entries</a>.
  </ol>

  <p class=XXX>The above is a rough approximation of what is needed for
  `<code>multipart/form-data</code>`, a more detailed parsing specification is to be
  written. Volunteers welcome.

  <p>Otherwise, if <var>mimeType</var>'s <a for="MIME type">essence</a> is
  "<code>application/x-www-form-urlencoded</code>", then:

  <ol>
   <li><p>Let <var>entries</var> be the result of
   <a lt="urlencoded parser">parsing</a> <var>bytes</var>.

   <li><p>If <var>entries</var> is failure, then <a>throw</a> a {{TypeError}}.

   <li><p>Return a new {{FormData}} object whose
   <a spec=xhr>entries</a> are <var>entries</var>.
  </ol>

  <p>Otherwise, <a>throw</a> a {{TypeError}}.

 <dt><i>JSON</i>
 <dd><p>Return the result of running <a>parse JSON from bytes</a> on <var>bytes</var>.

 <dt><i>text</i>
 <dd><p>Return the result of running <a>UTF-8 decode</a> on
 <var>bytes</var>.
</dl>

<p>Objects implementing the {{Body}} mixin also have an associated
<dfn id=concept-body-consume-body for=Body>consume body</dfn> algorithm, given a <var>type</var>,
runs these steps:

<ol>
 <li><p>If this object is <a for=Body>disturbed</a> or <a for=Body>locked</a>, return a new promise
 rejected with a {{TypeError}}.

 <li><p>Let <var>stream</var> be <a for=Body>body</a>'s
 <a for=body>stream</a> if <a for=Body>body</a> is
 non-null, or an <a>empty</a>
 {{ReadableStream}} object otherwise.

 <li><p>Let <var>reader</var> be the result of <a lt="get a reader" for=ReadableStream>getting
 a reader</a> from <var>stream</var>. If that threw an exception, return a new promise rejected
 with that exception.

 <li><p>Let <var>promise</var> be the result of
 <a lt="read all bytes" for=ReadableStream>reading all bytes</a> from
 <var>stream</var> with <var>reader</var>.

 <li><p>Return the result of transforming <var>promise</var> by a fulfillment handler that
 returns the result of the <a>package data</a> algorithm
 with its first argument, <var>type</var> and this object's
 <a for=Body>MIME type</a>.
 <!-- XXX IDL really needs to define "transforming". For now it is defined in
          https://www.w3.org/2001/tag/doc/promises-guide -->
</ol>

<p>The <dfn method for=Body><code>arrayBuffer()</code></dfn>
method, when invoked, must return the result of running
<a for=Body>consume body</a> with <i>ArrayBuffer</i>.

<p>The <dfn method for=Body><code>blob()</code></dfn> method, when
invoked, must return the result of running
<a for=Body>consume body</a> with <i>Blob</i>.

<p>The <dfn method for=Body><code>formData()</code></dfn> method,
when invoked, must return the result of running
<a for=Body>consume body</a> with <i>FormData</i>.

<p>The <dfn method for=Body><code>json()</code></dfn> method, when
invoked, must return the result of running
<a for=Body>consume body</a> with <i>JSON</i>.

<p>The <dfn method for=Body><code>text()</code></dfn> method, when
invoked, must return the result of running
<a for=Body>consume body</a> with <i>text</i>.


<h3 id=request-class>Request class</h3>

<!-- No client member, see
  https://github.com/w3c/ServiceWorker/issues/318
  https://github.com/w3c/ServiceWorker/issues/575 -->

<pre class=idl>
typedef (Request or USVString) RequestInfo;

[Exposed=(Window,Worker)]
interface Request {
  constructor(RequestInfo input, optional RequestInit init = {});

  readonly attribute ByteString method;
  readonly attribute USVString url;
  [SameObject] readonly attribute Headers headers;

  readonly attribute RequestDestination destination;
  readonly attribute USVString referrer;
  readonly attribute ReferrerPolicy referrerPolicy;
  readonly attribute RequestMode mode;
  readonly attribute RequestCredentials credentials;
  readonly attribute RequestCache cache;
  readonly attribute RequestRedirect redirect;
  readonly attribute DOMString integrity;
  readonly attribute boolean keepalive;
  readonly attribute boolean isReloadNavigation;
  readonly attribute boolean isHistoryNavigation;
  readonly attribute AbortSignal signal;

  [NewObject] Request clone();
};
Request includes Body;

dictionary RequestInit {
  ByteString method;
  HeadersInit headers;
  BodyInit? body;
  USVString referrer;
  ReferrerPolicy referrerPolicy;
  RequestMode mode;
  RequestCredentials credentials;
  RequestCache cache;
  RequestRedirect redirect;
  DOMString integrity;
  boolean keepalive;
  AbortSignal? signal;
  any window; // can only be set to null
};

enum RequestDestination { "", "audio", "audioworklet", "document", "embed", "font", "image", "manifest", "object", "paintworklet", "report", "script", "sharedworker", "style",  "track", "video", "worker", "xslt" };
enum RequestMode { "navigate", "same-origin", "no-cors", "cors" };
enum RequestCredentials { "omit", "same-origin", "include" };
enum RequestCache { "default", "no-store", "reload", "no-cache", "force-cache", "only-if-cached" };
enum RequestRedirect { "follow", "error", "manual" };
</pre>

<p class="note no-backref">"<code>serviceworker</code>" is omitted from
<a enum><code>RequestDestination</code></a> as it cannot be observed from JavaScript. Implementations
will still need to support it as a
<a for=request>destination</a>. "<code>websocket</code>" is
omitted from <a enum><code>RequestMode</code></a> as it cannot be used nor observed from JavaScript.

<p>A {{Request}} object has an associated
<dfn id=concept-request-request for=Request export>request</dfn> (a <a for=/>request</a>).

<p>A {{Request}} object also has an associated <dfn for=Request export>headers</dfn> (null or a
{{Headers}} object), initially null.

<p>A {{Request}} object has an associated <dfn for=Request>signal</dfn> (an {{AbortSignal}} object),
initially a new {{AbortSignal}} object.

<p>A {{Request}} object's <a for=Body>body</a> is its
<a for=Request>request</a>'s
<a for=request>body</a>.

<dl class=domintro>
 <dt><code><var>request</var> = new <a constructor lt="Request()">Request</a>(<var>input</var> [,
 <var>init</var>])</code>
 <dd>
  <p>Returns a new <var>request</var> whose {{Request/url}} property is <var>input</var> if
  <var>input</var> is a string, and <var>input</var>'s {{Request/url}} if <var>input</var> is a
  {{Request}} object.

  <p>The <var>init</var> argument is an object whose properties can be set as follows:</p>

  <dl>
   <dt>{{RequestInit/method}}
   <dd>A string to set <var>request</var>'s {{Request/method}}.

   <dt>{{RequestInit/headers}}
   <dd>A {{Headers}} object, an object literal, or an array of two-item arrays to set
   <var>request</var>'s {{Request/headers}}.

   <dt>{{RequestInit/body}}
   <dd>A {{BodyInit}} object or null to set <var>request</var>'s <a for=request>body</a>.

   <dt>{{RequestInit/referrer}}
   <dd>A string whose value is a same-origin URL, "<code>about:client</code>", or the empty string,
   to set <var>request</var>'s <a>referrer</a>.

   <dt>{{RequestInit/referrerPolicy}}
   <dd>A <a for=/>referrer policy</a> to set <var>request</var>'s {{Request/referrerPolicy}}.

   <dt>{{RequestInit/mode}}
   <dd>A string to indicate whether the request will use CORS, or will be restricted to same-origin
   URLs. Sets <var>request</var>'s {{Request/mode}}.

   <dt>{{RequestInit/credentials}}
   <dd>A string indicating whether credentials will be sent with the request always, never, or only
   when sent to a same-origin URL. Sets <var>request</var>'s {{Request/credentials}}.

   <dt>{{RequestInit/cache}}
   <dd>A string indicating how the request will interact with the browser's cache to set
   <var>request</var>'s {{Request/cache}}.

   <dt>{{RequestInit/redirect}}
   <dd>A string indicating whether <var>request</var> follows redirects, results in an error upon
   encountering a redirect, or returns the redirect (in an opaque fashion). Sets
   <var>request</var>'s {{Request/redirect}}.

   <dt>{{RequestInit/integrity}}
   <dd>A cryptographic hash of the resource to be fetched by <var>request</var>. Sets
   <var>request</var>'s {{Request/integrity}}.

   <dt>{{RequestInit/keepalive}}
   <dd>A boolean to set <var>request</var>'s {{Request/keepalive}}.

   <dt>{{RequestInit/signal}}
   <dd>An {{AbortSignal}} to set <var>request</var>'s {{Request/signal}}.

   <dt>{{RequestInit/window}}
   <dd>Can only be null. Used to disassociate <var>request</var> from any {{Window}}.
  </dl>

 <dt><code><var>request</var> . <a attribute for=Request>method</a></code>
 <dd>Returns <var>request</var>'s HTTP method, which is "<code>GET</code>" by default.

 <dt><code><var>request</var> . <a attribute for=Request>url</a></code>
 <dd>Returns the URL of <var>request</var> as a string.

 <dt><code><var>request</var> . <a attribute for=Request>headers</a></code>
 <dd>Returns a {{Headers}} object consisting of the headers associated with <var>request</var>.
 Note that headers added in the network layer by the user agent will not be accounted for in this
 object, e.g., the "<code>Host</code>" header.

 <dt><code><var>request</var> . <a attribute for=Request>destination</a></code>
 <dd>Returns the kind of resource requested by <var>request</var>, e.g., "<code>document</code>" or
 "<code>script</code>".

 <dt><code><var>request</var> . <a attribute for=Request>referrer</a></code>
 <dd>Returns the referrer of <var>request</var>. Its value can be a same-origin URL if
 explicitly set in <var>init</var>, the empty string to indicate no referrer, and
 "<code>about:client</code>" when defaulting to the global's default. This is used during
 fetching to determine the value of the `<code>Referer</code>` header of the request being made.

 <dt><code><var>request</var> . <a attribute for=Request>referrerPolicy</a></code>
 <dd>Returns the referrer policy associated with <var>request</var>. This is used during
 fetching to compute the value of the <var>request</var>'s referrer.

 <dt><code><var>request</var> . <a attribute for=Request>mode</a></code>
 <dd>Returns the <a>mode</a> associated with <var>request</var>, which is a string indicating
 whether the request will use CORS, or will be restricted to same-origin URLs.

 <dt><code><var>request</var> . <a attribute for=Request>credentials</a></code>
 <dd>Returns the <a>credentials mode</a> associated with <var>request</var>, which is a string
 indicating whether credentials will be sent with the request always, never, or only when sent to a
 same-origin URL.

 <dt><code><var>request</var> . <a attribute for=Request>cache</a></code>
 <dd>Returns the <a>cache mode</a> associated with <var>request</var>, which is a string indicating
 how the request will interact with the browser's cache when fetching.

 <dt><code><var>request</var> . <a attribute for=Request>redirect</a></code>
 <dd>Returns the <a>redirect mode</a> associated with <var>request</var>, which is a string
 indicating how redirects for the request will be handled during fetching. A <a for=/>request</a>
 will follow redirects by default.

 <dt><code><var>request</var> . <a attribute for=Request>integrity</a></code>
 <dd>Returns <var>request</var>'s subresource integrity metadata, which is a cryptographic hash of
 the resource being fetched. Its value consists of multiple hashes separated by whitespace. [[SRI]]

 <dt><code><var>request</var> . <a attribute for=Request>keepalive</a></code>
 <dd>Returns a boolean indicating whether or not <var>request</var> can outlive the global in which
 it was created.

 <dt><code><var>request</var> . <a attribute for=Request>isReloadNavigation</a></code>
 <dd>Returns a boolean indicating whether or not <var>request</var> is for a reload navigation.

 <dt><code><var>request</var> . <a attribute for=Request>isHistoryNavigation</a></code>
 <dd>Returns a boolean indicating whether or not <var>request</var> is for a history
 navigation (a.k.a. back-foward navigation).

 <dt><code><var>request</var> . <a attribute for=Request>signal</a></code>
 <dd>Returns the signal associated with <var>request</var>, which is an
 {{AbortSignal}} object indicating whether or not <var>request</var> has been aborted, and its abort
 event handler.
</dl>

<hr>

<p>The
<dfn constructor for=Request id=dom-request><code>Request(<var>input</var>, <var>init</var>)</code></dfn>
constructor must run these steps:

<ol>
 <li><p>Let <var>request</var> be null.

 <li><p>Let <var>fallbackMode</var> be null.

 <li><p>Let <var>fallbackCredentials</var> be null.

 <li><p>Let <var>baseURL</var> be <a>current settings object</a>'s
 <a for="environment settings object">API base URL</a>.

 <li><p>Let <var>signal</var> be null.

 <li>
  <p>If <var>input</var> is a string, then:

  <ol>
   <li><p>Let <var>parsedURL</var> be the result of
   <a lt="url parser">parsing</a> <var>input</var> with
   <var>baseURL</var>.

   <li><p>If <var>parsedURL</var> is failure, then <a>throw</a> a {{TypeError}}.

   <li><p>If <var>parsedURL</var> <a lt="include credential">includes credentials</a>, then
   <a>throw</a> a {{TypeError}}.

   <li><p>Set <var>request</var> to a new <a for=/>request</a> whose
   <a for=request>url</a> is <var>parsedURL</var>.

   <li><p>Set <var>fallbackMode</var> to "<code>cors</code>".

   <li><p>Set <var>fallbackCredentials</var> to "<code>same-origin</code>".
  </ol>

 <li>
  <p>Otherwise (<var>input</var> is a {{Request}} object):

  <ol>
   <li><p>Set <var>request</var> to <var>input</var>'s
   <a for=Request>request</a>.

   <li><p>Set <var>signal</var> to <var>input</var>'s <a for=Request>signal</a>.
  </ol>

 <li><p>Let <var>origin</var> be <a>current settings object</a>'s
 <a for="environment settings object">origin</a>.

 <li><p>Let <var>window</var> be "<code>client</code>".

 <li><p>If <var>request</var>'s <a for=request>window</a> is
 an <a>environment settings object</a> and its
 <a for="environment settings object">origin</a> is <a>same origin</a> with
 <var>origin</var>, set <var>window</var> to <var>request</var>'s
 <a for=request>window</a>.

 <li><p>If <var>init</var>["{{RequestInit/window}}"] <a for=map>exists</a> and is non-null, then
 <a>throw</a> a {{TypeError}}.

 <li><p>If <var>init</var>["{{RequestInit/window}}"] <a for=map>exists</a>, then set
 <var>window</var> to "<code>no-window</code>".

 <li>
  <p>Set <var>request</var> to a new <a for=/>request</a> with the following properties:

  <dl>
   <dt><a for=request>URL</a>
   <dd><var>request</var>'s <a for=request>current URL</a>.

   <dt><a for=request>method</a>
   <dd><var>request</var>'s <a for=request>method</a>.

   <dt><a for=request>header list</a>
   <dd>A copy of <var>request</var>'s <a for=request>header list</a>.

   <dt><a>unsafe-request flag</a>
   <dd>Set.

   <dt><a for=request>client</a>
   <dd><a>Current settings object</a>.

   <dt><a for=request>window</a>
   <dd><var>window</var>.

   <dt><a for=request>priority</a>
   <dd><var>request</var>'s <a for=request>priority</a>.

   <dt><a for=request>origin</a>
   <dd>"<code>client</code>".

   <dt><a for=request>referrer</a>
   <dd><var>request</var>'s <a for=request>referrer</a>.

   <dt><a for=request>referrer policy</a>
   <dd><var>request</var>'s <a for=request>referrer policy</a>.

   <dt><a for=request>mode</a>
   <dd><var>request</var>'s <a for=request>mode</a>.

   <dt><a for=request>credentials mode</a>
   <dd><var>request</var>'s <a for=request>credentials mode</a>.

   <dt><a for=request>cache mode</a>
   <dd><var>request</var>'s <a for=request>cache mode</a>.

   <dt><a for=request>redirect mode</a>
   <dd><var>request</var>'s <a for=request>redirect mode</a>.

   <dt><a for=request>integrity metadata</a>
   <dd><var>request</var>'s <a for=request>integrity metadata</a>.

   <dt><a>keepalive flag</a>
   <dd><var>request</var>'s <a>keepalive flag</a>.

   <dt><a for=request>reload-navigation flag</a>
   <dd><var>request</var>'s <a for=request>reload-navigation flag</a>.

   <dt><a for=request>history-navigation flag</a>
   <dd><var>request</var>'s <a for=request>history-navigation flag</a>.
  </dl>

 <li>
  <p>If <var>init</var> <a for=map>is not empty</a>, then:

  <ol>
   <li><p>If <var>request</var>'s <a for=request>mode</a> is
   "<code>navigate</code>", then set it to "<code>same-origin</code>".
   <!-- This works because we have reset request's client too. -->

   <li><p>Unset <var>request</var>'s <a for=request>reload-navigation flag</a>.

   <li><p>Unset <var>request</var>'s <a for=request>history-navigation flag</a>.

   <li><p>Set <var>request</var>'s <a for=request>referrer</a> to
   "<code>client</code>"

   <li><p>Set <var>request</var>'s <a for=request>referrer policy</a> to the empty string.
  </ol>

  <p class=note>This is done to ensure that when a service worker "redirects" a request, e.g., from
  an image in a cross-origin style sheet, and makes modifications, it no longer appears to come from
  the original source (i.e., the cross-origin style sheet), but instead from the service worker that
  "redirected" the request. This is important as the original source might not even be able to
  generate the same kind of requests as the service worker. Services that trust the original source
  could therefore be exploited were this not done, although that is somewhat farfetched.

 <li>
  <p>If <var>init</var>["{{RequestInit/referrer}}"] <a for=map>exists</a>, then:

  <ol>
   <li><p>Let <var>referrer</var> be <var>init</var>["{{RequestInit/referrer}}"].

   <li><p>If <var>referrer</var> is the empty string, then set <var>request</var>'s
   <a for=request>referrer</a> to "<code>no-referrer</code>".

   <li>
    <p>Otherwise:

    <ol>
     <li><p>Let <var>parsedReferrer</var> be the result of <a lt="url parser">parsing</a>
     <var>referrer</var> with <var>baseURL</var>.

     <li><p>If <var>parsedReferrer</var> is failure, then <a>throw</a> a {{TypeError}}.

     <li>
      <p>If one of the following is true

      <ul class=brief>
       <li><p><var>parsedReferrer</var>'s <a>cannot-be-a-base-URL flag</a> is set,
       <a for=url>scheme</a> is "<code>about</code>", and <a for=url>path</a> contains a single
       string "<code>client</code>"

       <li><p><var>parsedReferrer</var>'s <a for=url>origin</a> is not <a>same origin</a> with
       <var>origin</var>
      </ul>

      <p>then set <var>request</var>'s <a for=request>referrer</a> to "<code>client</code>".
      <!-- This can happen when you create a fresh request with values from an older request.
           Throwing would be rather hostile as preventing it requires implementing the same-origin
           check in developer space. -->

     <li><p>Otherwise, set <var>request</var>'s <a for=request>referrer</a> to
     <var>parsedReferrer</var>.
    </ol>
  </ol>

 <li><p>If <var>init</var>["{{RequestInit/referrerPolicy}}"] <a for=map>exists</a>, then set
 <var>request</var>'s <a for=request>referrer policy</a> to it.

 <li><p>Let <var>mode</var> be <var>init</var>["{{RequestInit/mode}}"] if it <a for=map>exists</a>,
 and <var>fallbackMode</var> otherwise.

 <li><p>If <var>mode</var> is "<code>navigate</code>", then <a>throw</a> a {{TypeError}}.

 <li><p>If <var>mode</var> is non-null, set <var>request</var>'s
 <a for=request>mode</a> to <var>mode</var>.

 <li><p>Let <var>credentials</var> be <var>init</var>["{{RequestInit/credentials}}"] if it
 <a for=map>exists</a>, and <var>fallbackCredentials</var> otherwise.

 <li><p>If <var>credentials</var> is non-null, set <var>request</var>'s
 <a for=request>credentials mode</a> to
 <var>credentials</var>.

 <li><p>If <var>init</var>["{{RequestInit/cache}}"] <a for=map>exists</a>, then set
 <var>request</var>'s <a for=request>cache mode</a> to it.

 <li><p>If <var>request</var>'s <a for=request>cache mode</a> is "<code>only-if-cached</code>" and
 <var>request</var>'s <a for=request>mode</a> is <em>not</em> "<code>same-origin</code>", then
 <a>throw</a> a {{TypeError}}.

 <li><p>If <var>init</var>["{{RequestInit/redirect}}"] <a for=map>exists</a>, then set
 <var>request</var>'s <a for=request>redirect mode</a> to it.

 <li><p>If <var>init</var>["{{RequestInit/integrity}}"] <a for=map>exists</a>, then set
 <var>request</var>'s <a for=request>integrity metadata</a> to it.

 <li><p>If <var>init</var>["{{RequestInit/keepalive}}"] <a for=map>exists</a>, then set
 <var>request</var>'s <a>keepalive flag</a> if <var>init</var>["{{RequestInit/keepalive}}"] is true,
 and unset it otherwise.

 <li>
  <p>If <var>init</var>["{{RequestInit/method}}"] <a for=map>exists</a>, then:

  <ol>
   <li><p>Let <var>method</var> be <var>init</var>["{{RequestInit/method}}"].

   <li><p>If <var>method</var> is not a <a for=/>method</a> or <var>method</var> is a
   <a>forbidden method</a>, then <a>throw</a> a {{TypeError}}.

   <li><p><a lt=normalize for=method>Normalize</a> <var>method</var>.

   <li><p>Set <var>request</var>'s <a for=request>method</a> to <var>method</var>.
  </ol>

 <li><p>If <var>init</var>["{{RequestInit/signal}}"] <a for=map>exists</a>, then set
 <var>signal</var> to it.

 <li><p>Let <var>r</var> be a new {{Request}} object associated with <var>request</var>.

 <li><p>If <var>signal</var> is not null, then make <var>r</var>'s <a for=Request>signal</a>
 <a for=AbortSignal>follow</a> <var>signal</var>.

 <li><p>Set <var>r</var>'s <a for=Request>headers</a> to a new {{Headers}} object, whose
 <a for=Headers>header list</a> is <var>request</var>'s <a for=request>header list</a>, and
 <a for=Headers>guard</a> is "<code>request</code>".

 <li>
  <p>If <var>init</var> <a for=map>is not empty</a>, then:

  <p class=note>The headers are sanitised as they might contain headers that are not allowed by this
  mode. Otherwise, they were previously sanitised or are unmodified since creation by a privileged
  API.

  <ol>
   <li><p>Let <var>headers</var> be a copy of <var>r</var>'s <a for=Request>headers</a> and its
   associated <a for=Headers>header list</a>.

   <li><p>If <var>init</var>["{{RequestInit/headers}}"] <a for=map>exists</a>, then set
   <var>headers</var> to <var>init</var>["{{RequestInit/headers}}"].

   <li><p>Empty <var>r</var>'s <a for=Request>headers</a>'s <a for=Headers>header list</a>.

   <li>
    <p>If <var>r</var>'s <a for=Request>request</a>'s <a for=request>mode</a> is
    "<code>no-cors</code>", then:

    <ol>
     <li><p>If <var>r</var>'s <a for=Request>request</a>'s <a for=request>method</a> is not a
     <a>CORS-safelisted method</a>, then <a>throw</a> a {{TypeError}}.

     <li><p>Set <var>r</var>'s <a for=Request>headers</a>'s <a for=Headers>guard</a> to
     "<code>request-no-cors</code>".
    </ol>
   </li>

   <li><p>If <var>headers</var> is a <code>Headers</code> object, then <a for=list>for each</a>
   <var>header</var> in its <a for=Headers>header list</a>, <a for=Headers>append</a>
   <var>header</var>'s <a for=header>name</a>/<var>header</var>'s <a for=header>value</a> to
   <var>r</var>'s {{Headers}} object.

   <li><p>Otherwise, <a for=Headers>fill</a> <var>r</var>'s {{Headers}} object with
   <var>headers</var>.
  </ol>
 </li>

 <li><p>Let <var>inputBody</var> be <var>input</var>'s
 <a for=Request>request</a>'s <a for=request>body</a>
 if <var>input</var> is a {{Request}} object, and null otherwise.

 <li><p>If either <var>init</var>["{{RequestInit/body}}"] <a for=map>exists</a> and is non-null or
 <var>inputBody</var> is non-null, and <var>request</var>'s <a for=request>method</a> is
 `<code>GET</code>` or `<code>HEAD</code>`, then <a>throw</a> a {{TypeError}}.

 <li><p>Let <var>body</var> be <var>inputBody</var>.

 <li>
  <p>If <var>init</var>["{{RequestInit/body}}"] <a for=map>exists</a> and is non-null, then:

  <ol>
   <li><p>Let <var>Content-Type</var> be null.

   <li><p>If <var>init</var>["{{RequestInit/keepalive}}"] <a for=map>exists</a> and is true, then
   set <var>body</var> and <var>Content-Type</var> to the result of <a for=BodyInit>extracting</a>
   <var>init</var>["{{RequestInit/body}}"], with the <var>keepalive flag</var> set.

   <li><p>Otherwise, set <var>body</var> and <var>Content-Type</var> to the result of
   <a for=BodyInit>extracting</a> <var>init</var>["{{RequestInit/body}}"].

   <li><p>If <var>Content-Type</var> is non-null and <var>r</var>'s <a for=Request>headers</a>'s
   <a for=Headers>header list</a> <a for="header list">does not contain</a>
   `<code>Content-Type</code>`, then <a for=Headers>append</a>
   `<code>Content-Type</code>`/<var>Content-Type</var> to <var>r</var>'s <a for=Request>headers</a>.
  </ol>

 <li>
  <p>If <var>body</var> is non-null and <var>body</var>'s <a for=body>source</a> is null, then:

  <ol>
   <li><p>If <var>r</var>'s <a for=Request>request</a>'s <a for=request>mode</a> is neither
   "<code>same-origin</code>" nor "<code>cors</code>", then throw a {{TypeError}}.

   <li><p>Set <var>r</var>'s <a for=Request>request</a>'s
   <a for=request>use-CORS-preflight flag</a>.
  </ol>

 <li><p>If <var>inputBody</var> is <var>body</var> and <var>input</var> is <a for=Body>disturbed</a>
 or <a for=Body>locked</a>, then <a>throw</a> a {{TypeError}}.

 <!-- Any steps after this must not throw. -->

 <li>
  <p>If <var>inputBody</var> is <var>body</var> and <var>inputBody</var> is non-null, then:

  <ol>
   <li><p>Let <var>ws</var> and <var>rs</var> be the <a>writable side</a> and <a>readable side</a>
   of an <a>identity transform stream</a>, respectively.</li>

   <li>
    <p>Let <var>promise</var> be the result of calling
    <a abstract-op>ReadableStreamPipeTo</a>(<var>inputBody</var>, <var>ws</var></var>, false,
    false, false, undefined).

    <p class="note no-backref">This makes <var>inputBody</var>'s <a for=body>stream</a>
    <a for=ReadableStream>locked</a> and <a for=ReadableStream>disturbed</a> immediately.
   </li>

   <li><p>Set <var>promise</var>.\[[PromiseIsHandled]]</var> to true.

   <li><p>Set <var>body</var> to a new <a for=/>body</a> whose <a for=body>stream</a> is
   <var>rs</var>, whose <a for=body>source</a> is <var>inputBody</var>'s <a for=body>source</a>, and
   whose <a for=body>total bytes</a> is <var>inputBody</var>'s <a for=body>total bytes</a>.
  </ol>

 <li><p>Set <var>r</var>'s <a for=Request>request</a>'s <a for=request>body</a> to <var>body</var>.

 <li><p>Set <var>r</var>'s <a for=Body>MIME type</a> to the result of
 <a for="header list">extracting a MIME type</a> from <var>r</var>'s <a for=Request>request</a>'s
 <a for=request>header list</a>.

 <li><p>Return <var>r</var>.
</ol>

<p>The <dfn attribute for=Request><code>method</code></dfn> attribute's getter, when invoked, must
return the <a>context object</a>'s <a for=Request>request</a>'s <a for=request>method</a>.

<p>The <dfn attribute for=Request><code>url</code></dfn> attribute's getter, when invoked, must
return the <a>context object</a>'s <a for=Request>request</a>'s <a for=request>URL</a>,
<a lt="url serializer">serialized</a>.

<p>The <dfn attribute for=Request><code>headers</code></dfn> attribute's getter, when invoked, must
return the <a>context object</a>'s <a for=Request>headers</a>.

<p>The <dfn attribute for=Request><code>destination</code></dfn> attribute's getter, when invoked,
must return the <a>context object</a>'s <a for=Request>request</a>'s <a for=request>destination</a>.

<p>The <dfn attribute for=Request><code>referrer</code></dfn> attribute's getter, when invoked, must
return the empty string if the <a>context object</a>'s <a for=Request>request</a>'s
<a for=request>referrer</a> is "<code>no-referrer</code>", "<code>about:client</code>" if the
<a>context object</a>'s <a for=Request>request</a>'s <a for=request>referrer</a> is
"<code>client</code>", and the <a>context object</a>'s <a for=Request>request</a>'s
<a for=request>referrer</a>, <a lt="url serializer">serialized</a>, otherwise.

<p>The <dfn attribute for=Request><code>referrerPolicy</code></dfn> attribute's getter, when
invoked, must return the <a>context object</a>'s <a for=Request>request</a>'s
<a for=request>referrer policy</a>.

<p>The <dfn attribute for=Request><code>mode</code></dfn> attribute's getter, when invoked, must
return the <a>context object</a>'s <a for=Request>request</a>'s <a for=request>mode</a>.

<p>The <dfn attribute for=Request><code>credentials</code></dfn> attribute's getter, when invoked,
must return the <a>context object</a>'s <a for=Request>request</a>'s
<a for=request>credentials mode</a>.

<p>The <dfn attribute for=Request><code>cache</code></dfn> attribute's getter, when invoked, must
return the <a>context object</a>'s <a for=Request>request</a>'s <a for=request>cache mode</a>.

<p>The <dfn attribute for=Request><code>redirect</code></dfn> attribute's getter, when invoked, must
return the <a>context object</a>'s <a for=Request>request</a>'s <a for=request>redirect mode</a>.

<p>The <dfn attribute for=Request><code>integrity</code></dfn> attribute's getter, when invoked,
must return the <a>context object</a>'s <a for=Request>request</a>'s
<a for=request>integrity metadata</a>.

<p>The <dfn attribute for=Request><code>keepalive</code></dfn> attribute's getter, when invoked,
must return true if the <a>context object</a>'s <a for=Request>request</a>'s <a>keepalive flag</a>
is set, and false otherwise.

<p>The <dfn attribute for=Request><code>isReloadNavigation</code></dfn> attribute's getter, when
invoked, must return true if the <a>context object</a>'s <a for=Request>request</a>'s
<a for=request>reload-navigation flag</a> is set, and false otherwise.

<p>The <dfn attribute for=Request><code>isHistoryNavigation</code></dfn> attribute's getter, when
invoked, must return true if the <a>context object</a>'s <a for=Request>request</a>'s
<a for=request>history-navigation flag</a> is set, and false otherwise.

<p>The <dfn attribute for=Request><code>signal</code></dfn> attribute's getter, when invoked, must
return the <a>context object</a>'s <a for="Request">signal</a>.

<hr>

<p>The <dfn method for=Request><code>clone()</code></dfn> method, when invoked, must
run these steps:

<ol>
 <li><p>If the <a>context object</a> is <a for=Body>disturbed</a> or <a for=Body>locked</a>, then
 <a>throw</a> a {{TypeError}}.

 <li><p>Let <var>clonedRequestObject</var> be a new {{Request}} object.

 <li><p>Let <var>clonedRequest</var> be the result of <a lt=clone for=request>cloning</a> the
 <a>context object</a>'s <a for=Request>request</a>.

 <li><p>Set <var>clonedRequestObject</var>'s <a for=Request>request</a> to <var>clonedRequest</var>.

 <li>
  <p>Set <var>clonedRequestObject</var>'s <a for=Request>headers</a> to a new {{Headers}} object
  with the following properties:

  <dl>
   <dt><a for=Headers>header list</a>
   <dd><var>clonedRequest</var>'s <a for=Headers>header list</a>.

   <dt><a for=Headers>guard</a>
   <dd>The <a>context object</a>'s <a for=Request>headers</a>'s <a for=Headers>guard</a>.
  </dl>
 </li>

 <li><p>Make <var>clonedRequestObject</var>'s <a for=Request>signal</a>
 <a for=AbortSignal>follow</a> the <a>context object</a>'s <a for=Request>signal</a>.

 <li><p>Return <var>clonedRequestObject</var>.
</ol>


<h3 id=response-class>Response class</h3>

<pre class=idl>[Exposed=(Window,Worker)]
interface Response {
  constructor(optional BodyInit? body = null, optional ResponseInit init = {});

  [NewObject] static Response error();
  [NewObject] static Response redirect(USVString url, optional unsigned short status = 302);

  readonly attribute ResponseType type;

  readonly attribute USVString url;
  readonly attribute boolean redirected;
  readonly attribute unsigned short status;
  readonly attribute boolean ok;
  readonly attribute ByteString statusText;
  [SameObject] readonly attribute Headers headers;

  [NewObject] Response clone();
};
Response includes Body;

dictionary ResponseInit {
  unsigned short status = 200;
  ByteString statusText = "";
  HeadersInit headers;
};

enum ResponseType { "basic", "cors", "default", "error", "opaque", "opaqueredirect" };
</pre>

<p>A {{Response}} object has an associated
<dfn id=concept-response-response for=Response export>response</dfn> (a
<a for=/>response</a>).

<p>A {{Response}} object also has an associated <dfn for=Response export>headers</dfn> (null or a
{{Headers}} object), initially null.

<p>A {{Response}} object's <a for=Body>body</a> is its
<a for=Response>response</a>'s <a for=response>body</a>.

<p>The
<dfn constructor for=Response id=dom-response><code>Response(<var>body</var>, <var>init</var>)</code></dfn>
constructor, when invoked, must run these steps:

<ol>
 <li><p>If <var>init</var>["{{ResponseInit/status}}"] is not in the range <code>200</code> to
 <code>599</code>, inclusive, then <a>throw</a> a <code>RangeError</code>.

 <li><p>If <var>init</var>["{{ResponseInit/statusText}}"] does not match the
 <a spec=http>reason-phrase</a> token production, then <a>throw</a> a {{TypeError}}.

 <li><p>Let <var>r</var> be a new {{Response}} object associated with a new <a for=/>response</a>.

 <li><p>Set <var>r</var>'s <a for=Response>headers</a> to a new {{Headers}} object, whose
 <a for=Headers>header list</a> is <var>r</var>'s <a for=Response>response</a>'s
 <a for=response>header list</a>, and <a for=Headers>guard</a> is "<code>response</code>".

 <li><p>Set <var>r</var>'s <a for=Response>response</a>'s <a for=response>status</a> to
 <var>init</var>["{{ResponseInit/status}}"].

 <li><p>Set <var>r</var>'s <a for=Response>response</a>'s <a for=response>status message</a> to
 <var>init</var>["{{ResponseInit/statusText}}"].

 <li><p>If <var>init</var>["{{ResponseInit/headers}}"] <a for=map>exists</a>, then
 <a for=Headers>fill</a> <var>r</var>'s <a for=Response>headers</a> with
 <var>init</var>["{{ResponseInit/headers}}"].

 <li>
  <p>If <var>body</var> is non-null, then:

  <ol>
   <li>
    <p>If <var>init</var>["{{ResponseInit/status}}"] is a <a>null body status</a>, then <a>throw</a>
    a {{TypeError}}.

    <p class="note no-backref"><code>101</code> is included in
    <a>null body status</a> due to its use elsewhere. It does not affect this step.

   <li><p>Let <var>Content-Type</var> be null.

   <li><p>Set <var>r</var>'s <a for=Response>response</a>'s <a for=response>body</a> and
   <var>Content-Type</var> to the result of <a for=BodyInit>extracting</a> <var>body</var>.

   <li><p>If <var>Content-Type</var> is non-null and <var>r</var>'s <a for=Response>response</a>'s
   <a for=response>header list</a> <a for="header list">does not contain</a>
   `<code>Content-Type</code>`, then <a for="header list">append</a>
   `<code>Content-Type</code>`/<var>Content-Type</var> to <var>r</var>'s
   <a for=Response>response</a>'s <a for=response>header list</a>.
  </ol>

 <li><p>Set <var>r</var>'s <a for=Body>MIME type</a> to the result of
 <a for="header list">extracting a MIME type</a> from <var>r</var>'s <a for=Response>response</a>'s
 <a for=response>header list</a>.

 <li><p>Set <var>r</var>'s <a for=Response>response</a>'s
 <a for=response>HTTPS state</a> to
 <a>current settings object</a>'s
 <a for="environment settings object">HTTPS state</a>.

 <li><p>Return <var>r</var>.
</ol>

<p>The static <dfn method for=Response><code>error()</code></dfn> method, when invoked, must run
these steps:

<ol>
 <li><p>Let <var>r</var> be a new {{Response}} object, whose <a for=Response>response</a> is a new
 <a>network error</a>.

 <li><p>Set <var>r</var>'s <a for=Response>headers</a> to a new {{Headers}} object whose
 <a for=Headers>guard</a> is "<code>immutable</code>".

 <li><p>Return <var>r</var>.
</ol>

<p>The static
<dfn method for=Response><code>redirect(<var>url</var>, <var>status</var>)</code></dfn>
method, when invoked, must run these steps:

<ol>
 <li><p>Let <var>parsedURL</var> be the result of
 <a lt="url parser">parsing</a> <var>url</var> with
 <a>current settings object</a>'s
 <a for="environment settings object">API base URL</a>.

 <li><p>If <var>parsedURL</var> is failure, then <a>throw</a> a {{TypeError}}.

 <li><p>If <var>status</var> is not a <a>redirect status</a>, then <a>throw</a> a
 <code>RangeError</code>.

 <li><p>Let <var>r</var> be a new {{Response}} object, whose <a for=Response>response</a> is a new
 <a for=/>response</a>.

 <li><p>Set <var>r</var>'s <a for=Response>headers</a> to a new {{Headers}} object whose
 <a for=Headers>guard</a> is "<code>immutable</code>".

 <li><p>Set <var>r</var>'s <a for=Response>response</a>'s
 <a for=response>status</a> to <var>status</var>.

 <li><p><a for="header list">Append</a> `<code>Location</code>` to <var>parsedURL</var>,
 <a lt="url serializer">serialized</a> and <a>isomorphic encoded</a>, in <var>r</var>'s
 <a for=Response>response</a>'s <a for=response>header list</a>.

 <li><p>Return <var>r</var>.
</ol>

<p>The <dfn attribute for=Response><code>type</code></dfn> attribute's getter, when invoked, must
return the <a>context object</a>'s <a for=Response>response</a>'s <a for=response>type</a>.

<p>The <dfn attribute for=Response><code>url</code></dfn> attribute's getter, when invoked, must
return the empty string if the <a>context object</a>'s <a for=Response>response</a>'s
<a for=response>URL</a> is null and the <a>context object</a>'s <a for=Response>response</a>'s
<a for=response>URL</a>, <a lt="url serializer">serialized</a> with the <i>exclude-fragment flag</i>
set, otherwise. [[!URL]]

<p>The <dfn attribute for=Response><code>redirected</code></dfn> attribute's getter, when invoked,
must return true if the <a>context object</a>'s <a for=Response>response</a>'s
<a for=response>URL list</a> has more than one item, and false otherwise.

<p class=note>To filter out <a for=/>responses</a> that are the result of a
redirect, do this directly through the API, e.g., <code>fetch(url, { redirect:"error" })</code>.
This way a potentially unsafe <a for=/>response</a> cannot accidentally leak.

<p>The <dfn attribute for=Response><code>status</code></dfn> attribute's getter, when invoked, must
return the <a>context object</a>'s <a for=Response>response</a>'s <a for=response>status</a>.

<p>The <dfn attribute for=Response><code>ok</code></dfn> attribute's getter, when invoked, must
return true if the <a>context object</a>'s <a for=Response>response</a>'s <a for=response>status</a>
is an <a>ok status</a>, and false otherwise.

<p>The <dfn attribute for=Response><code>statusText</code></dfn> attribute's getter, when invoked,
must return the <a>context object</a>'s <a for=Response>response</a>'s
<a for=response>status message</a>.

<p>The <dfn attribute for=Response><code>headers</code></dfn> attribute's getter, when invoked, must
return the <a>context object</a>'s <a for=Response>headers</a>.

<hr>

<p>The <dfn method for=Response><code>clone()</code></dfn> method, when invoked, must
run these steps:

<ol>
 <li><p>If the <a>context object</a> is <a for=Body>disturbed</a> or <a for=Body>locked</a>, then
 <a>throw</a> a {{TypeError}}.

 <li><p>Let <var>clonedResponseObject</var> be a new {{Response}} object.

 <li><p>Let <var>clonedResponse</var> be the result of <a lt=clone for=response>cloning</a> the
 <a>context object</a>'s <a for=Response>response</a>.

 <li><p>Set <var>clonedResponseObject</var>'s <a for=Response>response</a> to
 <var>clonedResponse</var>.

 <li><p>Set <var>clonedResponseObject</var>'s <a for=Request>headers</a> to a new {{Headers}} object
 whose <a for=Headers>header list</a> is set to <var>clonedResponse</var>'s
 <a for=Headers>header list</a>, and <a for=Headers>guard</a> is the <a>context object</a>'s
 <a for=Response>headers</a>'s <a for=Headers>guard</a>.

 <li><p>Return <var>clonedResponseObject</var>.

 <li><p>Return <var>clonedResponse</var>.
</ol>


<h3 id=fetch-method>Fetch method</h3>

<pre class=idl>
partial interface mixin WindowOrWorkerGlobalScope {
  [NewObject] Promise&lt;Response> fetch(RequestInfo input, optional RequestInit init = {});
};
</pre>

<p>The
<dfn id=dom-global-fetch method for=WindowOrWorkerGlobalScope><code>fetch(<var>input</var>, <var>init</var>)</code></dfn>
method, must run these steps:

<ol>
 <li><p>Let <var>p</var> be a new promise.

 <li><p>Let <var>requestObject</var> be the result of invoking the initial value of {{Request}} as
 constructor with <var>input</var> and <var>init</var> as arguments. If this throws an exception,
 reject <var>p</var> with it and return <var>p</var>.

 <li><p>Let <var>request</var> be <var>requestObject</var>'s <a for=Request>request</a>.

 <li>
  <p>If <var>requestObject</var>'s <a for=Request>signal</a>'s <a for=AbortSignal>aborted flag</a>
  is set, then:

  <ol>
   <li><p><a>Abort fetch</a> with <var>p</var>, <var>request</var>, and null.

   <li><p>Return <var>p</var>.
  </ol>

 <li>If <var>request</var>'s <a for=request>client</a>'s
 <a for="environment settings object">global object</a> is a {{ServiceWorkerGlobalScope}} object,
 then set <var>request</var>'s <a>service-workers mode</a> to "<code>none</code>".

 <li><p>Let <var>responseObject</var> be a new {{Response}} object and a new associated
 {{Headers}} object whose <a for=Headers>guard</a> is
 "<code>immutable</code>".

 <li>
  <p>Let <var>locallyAborted</var> be false.

  <p class=note>This lets us reject promises with predictable timing, when the request to abort
  comes from the same thread as the call to fetch.

 <li>
  <p><a for=AbortSignal lt=add>Add the following abort steps</a> to <var>requestObject</var>'s
  <a for=Request>signal</a>:

  <ol>
    <li><p>Set <var>locallyAborted</var> to true.

    <li><p><a>Abort fetch</a> with <var>p</var>, <var>request</var>, and
    <var>responseObject</var>.

    <li><p><a lt=terminated for=fetch>Terminate</a> the ongoing fetch with the aborted flag set.
  </ol>

 <li>
  <p>Run the following <a>in parallel</a>:

  <p><a for=/>Fetch</a> <var>request</var>.

  <p>To <a>process response</a> for <var>response</var>, run these substeps:

  <ol>
   <li><p>If <var>locallyAborted</var> is true, terminate these substeps.

   <li><p>If <var>response</var>'s <a for=response>aborted flag</a> is set, then <a>abort fetch</a>
   with <var>p</var>, <var>request</var>, and <var>responseObject</var>, and terminate these
   substeps.

   <li><p>If <var>response</var> is a <a>network error</a>, then reject <var>p</var> with a
   {{TypeError}} and terminate these substeps.

   <li><p>Associate <var>responseObject</var> with <var>response</var>.

   <li><p>Resolve <var>p</var> with <var>responseObject</var>.
  </ol>

 <li><p>Return <var>p</var>.
</ol>

<p>To <dfn>abort fetch</dfn> with a <var>promise</var>, <var>request</var>, and
<var>responseObject</var>, run these steps:

<ol>
 <li><p>Let <var>error</var> be an "<code><a exception>AbortError</a></code>" {{DOMException}}.

 <li>
  <p>Reject <var>promise</var> with <var>error</var>.

  <p class=note>This is a no-op if <var>promise</var> has already fulfilled.

 <li><p>If <var>request</var>'s <a for=request>body</a> is not null and is
 <a for=ReadableStream>readable</a>, then <a for=ReadableStream>cancel</a> <var>request</var>'s
 <a for=request>body</a> with <var>error</var>.

 <li><p>If <var>responseObject</var> is null, then return.

 <li><p>Let <var>response</var> be <var>responseObject</var>'s <a for=Response>response</a>.

 <li><p>If <var>response</var>'s <a for=response>body</a> is not null and is
 <a for=ReadableStream>readable</a>, then <a for=ReadableStream abstract-op>error</a>
 <var>response</var>'s <a for=response>body</a> with <var>error</var>.
</ol>


<h3 id=garbage-collection>Garbage collection</h3>

<p>The user agent may <a lt=terminated for=fetch>terminate</a> an ongoing fetch if that termination
is not observable through script.

<p class="note no-backref">"Observable through script" means observable through
<a><code>fetch()</code></a>'s arguments and return value. Other ways, such as
communicating with the server through a side-channel are not included.

<p class="note no-backref">The server being able to observe garbage collection has precedent, e.g.,
with {{WebSocket}} and {{XMLHttpRequest}} objects.

<div id=terminate-examples class="example no-backref">
 <p>The user agent can terminate the fetch because the termination cannot be observed.
 <pre><code class=lang-javascript>
fetch("https://www.example.com/")
</code></pre>

 <p>The user agent cannot terminate the fetch because the termination can be observed through
 the promise.
 <pre><code class=lang-javascript>
window.promise = fetch("https://www.example.com/")
</code></pre>

 <p>The user agent can terminate the fetch because the associated body is not observable.
 <pre><code class=lang-javascript>
window.promise = fetch("https://www.example.com/").then(res => res.headers)
</code></pre>

 <p>The user agent can terminate the fetch because the termination cannot be observed.
 <pre><code class=lang-javascript>
fetch("https://www.example.com/").then(res => res.body.getReader().closed)
</code></pre>

 <p>The user agent cannot terminate the fetch because one can observe the termination by registering
 a handler for the promise object.
 <pre><code class=lang-javascript>
window.promise = fetch("https://www.example.com/")
  .then(res => res.body.getReader().closed)
</code></pre>

 <p>The user agent cannot terminate the fetch as termination would be observable via the registered
 handler.
 <pre><code class=lang-javascript>
fetch("https://www.example.com/")
  .then(res => {
    res.body.getReader().closed.then(() => console.log("stream closed!"))
  })
</code></pre>

  <p>(The above examples of non-observability assume that built-in properties and functions, such as
  {{ReadableStream/getReader()|body.getReader()}}, have not been overwritten.)
</div>



<h2 id=websocket-protocol>WebSocket protocol alterations</h2>

<div class=note>
 <p>This section replaces part of the WebSocket protocol opening handshake client requirement to
 integrate it with algorithms defined in Fetch. This way CSP, cookies, HSTS, and other Fetch-related
 protocols are handled in a single location. Ideally the RFC would be updated with this language,
 but it is never that easy. The WebSocket API, defined in the HTML Standard, has been updated to use
 this language. [[!WSP]] [[!HTML]]

 <p>The way this works is by replacing The WebSocket Protocol's "establish a WebSocket connection"
 algorithm with a new one that integrates with Fetch. "Establish a WebSocket connection" consists of
 three algorithms: setting up a connection, creating and transmiting a handshake request, and
 validating the handshake response. That layering is different from Fetch, which first creates a
 handshake, then sets up a connection and transmits the handshake, and finally validates the
 response. Keep that in mind while reading these alterations.
</div>


<h3 id=websocket-connections>Connections</h3>

<p>To <dfn id=concept-websocket-connection-obtain>obtain a WebSocket connection</dfn>, given a
<var>url</var>, run these steps:

<ol>
 <li><p>Let <var ignore>host</var> be <var>url</var>'s <a for=url>host</a>.

 <li><p>Let <var ignore>port</var> be <var>url</var>'s <a for=url>port</a>.

 <li><p>Let <var ignore>secure</var> be false, if <var>url</var>'s <a for=url>scheme</a> is
 "<code>http</code>", and true otherwise.

 <li><p>Follow the requirements stated in step 2 to 5, inclusive, of the first set of steps in
 <a href=http://tools.ietf.org/html/rfc6455#section-4.1>section 4.1</a> of The WebSocket Protocol
 to establish a <a lt="obtain a WebSocket connection">WebSocket connection</a>.
 [[!WSP]]

 <li><p>If that established a connection, return it, and return failure otherwise.
</ol>

<p class=note>Although structured a little differently, carrying different properties, and
therefore not shareable, a WebSocket connection is very close to identical to an "ordinary"
<a>connection</a>.


<h3 id=websocket-opening-handshake>Opening handshake</h3>

<p>To <dfn id=concept-websocket-establish>establish a WebSocket connection</dfn>, given a
<var>url</var>, <var>protocols</var>, and <var>client</var>, run these steps:

<ol>
 <li>
  <p>Let <var>requestURL</var> be a copy of <var>url</var>, with its
  <a for=url>scheme</a> set to
  "<code>http</code>", if <var>url</var>'s
  <a for=url>scheme</a> is "<code>ws</code>", and
  to "<code>https</code>" otherwise.

  <p class="note no-backref">This change of scheme is essential to integrate well with
  <a lt=fetch for=/>fetching</a>. E.g., HSTS would not work without it. There is no real
  reason for WebSocket to have distinct schemes, it's a legacy artefact.
  [[!HSTS]]

 <li><p>Let <var>request</var> be a new <a for=/>request</a>, whose
 <a for=request>URL</a> is <var>requestURL</var>,
 <a for=request>client</a> is <var>client</var>,
 <a>service-workers mode</a> is "<code>none</code>",
 <a for=request>referrer</a> is "<code>no-referrer</code>",
 <a>synchronous flag</a> is set,
 <a for=request>mode</a> is "<code>websocket</code>",
 <a for=request>credentials mode</a> is
 "<code>include</code>",
 <a for=request>cache mode</a> is "<code>no-store</code>", and
 <a for=request>redirect mode</a> is "<code>error</code>".

 <li><p><a for="header list">Append</a>
 `<code>Upgrade</code>`/`<code>websocket</code>` to
 <var>request</var>'s <a for=request>header list</a>.

 <li><p><a for="header list">Append</a>
 `<code>Connection</code>`/`<code>Upgrade</code>` to
 <var>request</var>'s <a for=request>header list</a>.

 <li>
  <p>Let <var>keyValue</var> be a nonce consisting of a randomly selected 16-byte value that has
  been <a lt="forgiving-base64 encode">forgiving-base64-encoded</a> and <a>isomorphic encoded</a>.

  <p id=example-random-value class=example>If the randomly selected value was the byte sequence 0x01 0x02 0x03 0x04 0x05
  0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10, <var>keyValue</var> would be
  forgiving-base64-encoded to "<code>AQIDBAUGBwgJCgsMDQ4PEC==</code>" and isomorphic encoded
  to `<code>AQIDBAUGBwgJCgsMDQ4PEC==</code>`.

 <li><p><a for="header list">Append</a>
 `<code>Sec-WebSocket-Key</code>`/<var>keyValue</var> to
 <var>request</var>'s <a for=request>header list</a>.

 <li><p><a for="header list">Append</a>
 `<code>Sec-WebSocket-Version</code>`/`<code>13</code>` to
 <var>request</var>'s <a for=request>header list</a>.

 <li><p>For each <var>protocol</var> in <var>protocols</var>, <a for="header list">combine</a>
 `<code>Sec-WebSocket-Protocol</code>`/<var>protocol</var> in <var>request</var>'s
 <a for=request>header list</a>.

 <li>
  <p>Let <var>permessageDeflate</var> be a user-agent defined
  "<code>permessage-deflate</code>" extension <a for=/>header</a>
  <a for=header>value</a>. [[!WSP]]

  <p id=example-permessage-deflate class=example>`<code>permessage-deflate; client_max_window_bits</code>`

 <li><p><a for="header list">Append</a>
 `<code>Sec-WebSocket-Extensions</code>`/<var>permessageDeflate</var>
 to <var>request</var>'s <a for=request>header list</a>.

 <li><p>Let <var>response</var> be the result of <a lt=fetch for=/>fetching</a>
 <var>request</var>.

 <li><p>If <var>response</var> is a <a>network error</a> or its
 <a for=response>status</a> is not <code>101</code>,
 <a>fail the WebSocket connection</a>.

 <li>
  <p>If <var>protocols</var> is not the empty list and <a>extracting header list values</a> given
  `<code>Sec-WebSocket-Protocol</code>` and <var>response</var>'s <a for=request>header list</a>
  results in null, failure, or the empty byte sequence, then <a>fail the WebSocket connection</a>.

  <p class=note>This is different from the check on this header defined by The WebSocket Protocol.
  That only covers a subprotocol not requested by the client. This covers a subprotocol requested by
  the client, but not acknowledged by the server.

 <li><p>Follow the requirements stated step 2 to step 6, inclusive, of the last set of steps in
 <a href=http://tools.ietf.org/html/rfc6455#section-4.1>section 4.1</a> of The WebSocket Protocol
 to validate <var>response</var>. This either results in <a>fail the WebSocket connection</a>
 or <a>the WebSocket connection is established</a>.
</ol>

<p><dfn>Fail the WebSocket connection</dfn> and <dfn>the WebSocket connection is established</dfn>
are defined by The WebSocket Protocol. [[!WSP]]

<p class=warning>The reason redirects are not followed and this handshake is generally restricted is
because it could introduce serious security problems in a web browser context. For example, consider
a host with a WebSocket server at one path and an open HTTP redirector at another. Suddenly, any
script that can be given a particular WebSocket URL can be tricked into communicating to (and
potentially sharing secrets with) any host on the internet, even if the script checks that the URL
has the right hostname.
<!-- https://www.ietf.org/mail-archive/web/hybi/current/msg06951.html -->



<h2 id=data-urls><code>data:</code> URLs</h2>

<p>For an informative description of <code>data:</code> URLs, see RFC 2397. This section replaces
that RFC's normative processing requirements to be compatible with deployed content. [[RFC2397]]

<p>A <dfn><code>data:</code> URL struct</dfn> is a <a>struct</a> that consists of a
<dfn for="data: URL struct">MIME type</dfn> (a <a for=/>MIME type</a>) and a
<dfn for="data: URL struct">body</dfn> (a <a>byte sequence</a>).

<p>The <dfn export><code>data:</code> URL processor</dfn> takes a <a for=/>URL</a>
<var>dataURL</var> and then runs these steps:

<ol>
 <li><p>Assert: <var>dataURL</var>'s <a for=url>scheme</a> is "<code>data</code>".

 <li><p>Let <var>input</var> be the result of running the <a>URL serializer</a> on
 <var>dataURL</var> with the <i>exclude fragment flag</i> set.

 <li><p>Remove the leading "<code>data:</code>" string from <var>input</var>.

 <li><p>Let <var>position</var> point at the start of <var>input</var>.

 <li><p>Let <var>mimeType</var> be the result of <a>collecting a sequence of code points</a> that
 are not equal to U+002C (,), given <var>position</var>.

 <li>
  <p><a>Strip leading and trailing ASCII whitespace</a> from <var>mimeType</var>.

  <p class="note">This will only remove U+0020 SPACE <a>code points</a>, if any.

 <li><p>If <var>position</var> is past the end of <var>input</var>, then return failure.

 <li><p>Advance <var>position</var> by 1.

 <li><p>Let <var>encodedBody</var> be the remainder of <var>input</var>.

 <li><p>Let <var>body</var> be the <a>string percent decoding</a> of <var>encodedBody</var>.

 <li>
  <p>If <var>mimeType</var> ends with U+003B (;), followed by zero or more U+0020 SPACE, followed by
  an <a>ASCII case-insensitive</a> match for "<code>base64</code>", then:

  <ol>
   <li><p>Let <var>stringBody</var> be the <a>isomorphic decode</a> of <var>body</var>.

   <li><p>Set <var>body</var> to the <a>forgiving-base64 decode</a> of <var>stringBody</var>.

   <li><p>If <var>body</var> is failure, then return failure.

   <li><p>Remove the last 6 <a>code points</a> from <var>mimeType</var>.

   <li><p>Remove trailing U+0020 SPACE <a>code points</a> from <var>mimeType</var>, if any.

   <li><p>Remove the last U+003B (;) <a>code point</a> from <var>mimeType</var>.
  </ol>

 <li><p>If <var>mimeType</var> starts with U+003B (;), then prepend "<code>text/plain</code>"
 to <var>mimeType</var>.

 <li><p>Let <var>mimeTypeRecord</var> be the result of <a lt="parse a MIME type">parsing</a>
 <var>mimeType</var>.

 <li><p>If <var>mimeTypeRecord</var> is failure, then set <var>mimeTypeRecord</var> to
 <code>text/plain;charset=US-ASCII</code>.

 <li><p>Return a new <a><code>data:</code> URL struct</a> whose
 <a for="data: URL struct">MIME type</a> is <var>mimeTypeRecord</var> and
 <a for="data: URL struct">body</a> is <var>body</var>.
</ol>



<h2 id=background-reading class=no-num>Background reading</h2>

<p><em>This section and its subsections are informative only.</em>

<h3 id=http-header-layer-division dfn class=no-num>HTTP header layer division</h3>

<p>For the purposes of fetching, there is an API layer (HTML's
<code>img</code>, CSS' <code>background-image</code>), early fetch layer,
service worker layer, and network &amp; cache layer.
`<code>Accept</code>` and
`<code>Accept-Language</code>` are set in the early fetch layer
(typically by the user agent). Most other headers controlled by the user agent, such as
`<code>Accept-Encoding</code>`,
`<code>Host</code>`, and `<code>Referer</code>`, are
set in the network &amp; cache layer. Developers can set headers either at the API layer
or in the service worker layer (typically through a <a for=/><code>Request</code></a> object).
Developers have almost no control over
<a lt="forbidden header name">forbidden headers</a>, but can control
`<code>Accept</code>` and have the means to constrain and omit
`<code>Referer</code>` for instance.


<h3 id=atomic-http-redirect-handling dfn class=no-num>Atomic HTTP redirect handling</h3>

<p>Redirects (a <a for=/>response</a> whose
<a for=response>status</a> or
<a for=internal>internal response</a>'s (if any)
<a for=response>status</a> is a <a>redirect status</a>) are not exposed
to APIs. Exposing redirects might leak information not otherwise available through a cross-site
scripting attack.

<p id=example-xss-redirect class=example>A fetch to <code>https://example.org/auth</code> that includes a
<code>Cookie</code> marked <code>HttpOnly</code> could result in a redirect to
<code>https://other-origin.invalid/4af955781ea1c84a3b11</code>. This new URL contains a
secret. If we expose redirects that secret would be available through a cross-site
scripting attack.


<h3 id=basic-safe-cors-protocol-setup class=no-num>Basic safe CORS protocol setup</h3>

<p>For resources where data is protected through IP authentication or a firewall
(unfortunately relatively common still), using the <a>CORS protocol</a> is
<strong>unsafe</strong>. (This is the reason why the <a>CORS protocol</a> had to be
invented.)

<p>However, otherwise using the following <a for=/>header</a> is
<strong>safe</strong>:

<pre><code class=lang-http>
Access-Control-Allow-Origin: *
</code></pre>

<p>Even if a resource exposes additional information based on cookie or HTTP
authentication, using the above <a for=/>header</a> will not reveal
it. It will share the resource with APIs such as
{{XMLHttpRequest}}, much like it is already shared with
<code>curl</code> and <code>wget</code>.

<p>Thus in other words, if a resource cannot be accessed from a random device connected to
the web using <code>curl</code> and <code>wget</code> the aforementioned
<a for=/>header</a> is not to be included. If it can be accessed
however, it is perfectly fine to do so.


<h3 id=cors-protocol-and-http-caches class=no-num>CORS protocol and HTTP caches</h3>

<p>If <a>CORS protocol</a> requirements are more complicated than setting
`<a http-header><code>Access-Control-Allow-Origin</code></a>` to <code>*</code> or a static
<a for=/>origin</a>, `<code>Vary</code>` is to be used.
[[!HTML]]
[[!HTTP]] [[!HTTP-SEMANTICS]] [[!HTTP-COND]] [[!HTTP-CACHING]] [[!HTTP-AUTH]]

<pre id=example-vary-origin class=example><code class=lang-http>
Vary: Origin
</code></pre>

<p>In particular, consider what happens if `<code>Vary</code>` is <em>not</em> used and a server is
configured to send `<a http-header><code>Access-Control-Allow-Origin</code></a>` for a certain
resource only in response to a <a>CORS request</a>. When a user agent receives a response to a
non-<a>CORS request</a> for that resource (for example, as the result of a <a>navigation
request</a>), the response will lack `<a http-header><code>Access-Control-Allow-Origin</code></a>`
and the user agent will cache that response. Then, if the user agent subsequently encounters a
<a>CORS request</a> for the resource, it will use that cached response from the previous
non-<a>CORS request</a>, without `<a http-header><code>Access-Control-Allow-Origin</code></a>`.

<p>But if `<code>Vary: Origin</code>` is used in the same scenario described above, it will cause
the user agent to <a for=/>fetch</a> a response that includes
`<a http-header><code>Access-Control-Allow-Origin</code></a>`, rather than using the cached response
from the previous non-<a>CORS request</a> that lacks
`<a http-header><code>Access-Control-Allow-Origin</code></a>`.

<p>However, if `<a http-header><code>Access-Control-Allow-Origin</code></a>` is set to
<code>*</code> or a static <a for=/>origin</a> for a particular resource, then configure the server
to always send `<a http-header><code>Access-Control-Allow-Origin</code></a>` in responses for the
resource — for non-<a>CORS requests</a> as well as <a>CORS
requests</a> — and do not use `<code>Vary</code>`.


<h2 id=acknowledgments class=no-num>Acknowledgments</h2>

<p>Thanks to
Adam Barth,
Adam Lavin,
Alan Jeffrey,
Alexey Proskuryakov,
Andrés Gutiérrez,
Andrew Sutherland,
Ángel González,
Anssi Kostiainen,
Arkadiusz Michalski,
Arne Johannessen,
Arthur Barstow,
Asanka Herath,
Axel Rauschmayer,
Ben Kelly,
Benjamin Gruenbaum,
Benjamin Hawkes-Lewis,
Bert Bos,
Björn Höhrmann,
Boris Zbarsky,
Brad Hill,
Brad Porter,
Bryan Smith,
Caitlin Potter,
Cameron McCormack,
Chris Rebert,
Clement Pellerin,
Collin Jackson,
Daniel Robertson,
Daniel Veditz,
Dave Tapuska,
David Benjamin,
David Håsäther,
David Orchard,
Dean Jackson,
Devdatta Akhawe,
Domenic Denicola,
Dominic Farolino,
Dominique Hazaël-Massieux,
Doug Turner,
Douglas Creager,
Eero Häkkinen,
Ehsan Akhgari,
Emily Stark,
Eric Lawrence,
François Marier,
Frank Ellerman,
Frederick Hirsch,
Gary Blackwood,
Gavin Carothers,
Glenn Maynard,
Graham Klyne,
Hal Lockhart,
Hallvord R. M. Steen,
Harris Hancock,
Henri Sivonen,
Henry Story,
Hiroshige Hayashizaki,
Honza Bambas,
Ian Hickson,
Ilya Grigorik,
isonmad,
Jake Archibald<!-- technically B.J. Archibald -->,
James Graham,
Janusz Majnert,
Jeena Lee,
Jeff Carpenter,
Jeff Hodges,
Jeffrey Yasskin,
Jesse M. Heines,
Jianjun Chen,
Jinho Bang,
Jochen Eisinger,
John Wilander,
Jonas Sicking,
Jonathan Kingston,
Jonathan Watt,
최종찬 (Jongchan Choi),
Jörn Zaefferer,
Joseph Pecoraro,
Josh Matthews,
Julian Krispel-Samsel,
Julian Reschke,
송정기 (Jungkee Song),
Jussi Kalliokoski,
Jxck,
Kagami Sascha Rosylight,
Keith Yeung,
Kenji Baheux,
Lachlan Hunt,
Larry Masinter,
Liam Brummitt,
Louis Ryan,
Lucas Gonze,
Łukasz Anforowicz,
呂康豪 (Kang-Hao Lu),
Maciej Stachowiak,
Malisa<!-- malisas; GitHub -->,
Manfred Stock,
Manish Goregaokar,
Marc Silbey,
Marcos Caceres,
Marijn Kruisselbrink,
Mark Nottingham,
Mark S. Miller,
Martin Dürst,
Martin Thomson,
Matt Andrews,
Matt Falkenhagen,
Matt Oshry,
Matt Seddon,
Matt Womer,
Mhano Harkness,
Michael Kohler,
Michael™ Smith,
Mike Pennisi,
Mike West,
Mohamed Zergaoui,
Mohammed Zubair Ahmed<!-- M-ZubairAhmed; GitHub -->,
Moritz Kneilmann,
Ms2ger,
Nico Schlömer,
Nicolás Peña Moreno,
Nikhil Marathe,
Nikki Bee,
Nikunj Mehta,
Odin Hørthe Omdal,
Ondřej Žára,
O. Opsec,
Perry Jiang<!-- perryjiang; Github -->,
Philip Jägenstedt,
R. Auburn,
Raphael Kubo da Costa,
Rondinelly,
Rory Hewitt,
Ryan Sleevi,
Sébastien Cevey,
Sendil Kumar N,
Shao-xuan Kang,
Sharath Udupa,
Shivakumar Jagalur Matt,
Sigbjørn Finne,
Simon Pieters,
Simon Sapin,
Srirama Chandra Sekhar Mogali,
Stephan Paul,
Steven Salat,
Sunava Dutta,
Surya Ismail,
Takashi Toyoshima,
吉野剛史 (Takeshi Yoshino),
Thomas Roessler,
Thomas Steiner,
Thomas Wisniewski,
Tiancheng "Timothy" Gu,
Tobie Langel,
Tom Schuster,
Tomás Aparicio,
保呂毅 (Tsuyoshi Horo),
Tyler Close,
Ujjwal Sharma,
Vignesh Shanmugam,
Vladimir Dzhuvinov,
Wayne Carr,
Xabier Rodríguez,
Yehuda Katz,
Yoav Weiss,
Youenn Fablet<!-- youennf; GitHub -->,
平野裕 (Yutaka Hirano), and
Zhenbin Xu
for being awesome.

<p>This standard is written by
<a href=https://annevankesteren.nl/ lang=nl>Anne van Kesteren</a>
(<a href=https://www.mozilla.org/>Mozilla</a>,
<a href=mailto:annevk@annevk.nl>annevk@annevk.nl</a>).
